mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #4052 from Turnerj/feature-max-size-by-upload-type
FEATURE: Added maximum upload file size by type (on 3)
This commit is contained in:
commit
9aa60ed4f3
@ -148,6 +148,16 @@ NOTE: this only sets the configuration for your UploadField, this does NOT chang
|
|||||||
$this->getValidator()->setAllowedMaxFileSize($size);
|
$this->getValidator()->setAllowedMaxFileSize($size);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can also specify a default global maximum file size setting in your config for different file types. This is overridden when specifying the max allowed file size on the UploadField instance.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Upload_Validator:
|
||||||
|
default_max_file_size:
|
||||||
|
'[image]': '1m'
|
||||||
|
'[doc]': '5m'
|
||||||
|
'jpeg': 2000
|
||||||
|
```
|
||||||
|
|
||||||
### Preview dimensions
|
### Preview dimensions
|
||||||
Set the dimensions of the image preview. By default the max width is set to 80 and the max height is set to 60.
|
Set the dimensions of the image preview. By default the max width is set to 80 and the max height is set to 60.
|
||||||
|
|
||||||
@ -297,6 +307,19 @@ Certain default values for the above can be configured using the YAML config sys
|
|||||||
|
|
||||||
The above settings can also be set on a per-instance basis by using `setConfig` with the appropriate key.
|
The above settings can also be set on a per-instance basis by using `setConfig` with the appropriate key.
|
||||||
|
|
||||||
|
The `Upload_Validator` class has configuration options for setting the `default_max_file_size`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Upload_Validator:
|
||||||
|
default_max_file_size:
|
||||||
|
'[image]': '1m'
|
||||||
|
'[doc]': '5m'
|
||||||
|
'jpeg': 2000
|
||||||
|
```
|
||||||
|
|
||||||
|
You can specify the file extension or the app category (as specified in the `File` class) in square brackets. It supports setting the file size in bytes or using the syntax supported by `File::ini2bytes()`.
|
||||||
|
|
||||||
|
|
||||||
You can also configure the underlying `[api:Upload]` class, by using the YAML config system.
|
You can also configure the underlying `[api:Upload]` class, by using the YAML config system.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
@ -305,6 +305,16 @@ class Upload extends Controller {
|
|||||||
*/
|
*/
|
||||||
class Upload_Validator {
|
class Upload_Validator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains a list of the max file sizes shared by
|
||||||
|
* all upload fields. This is then duplicated into the
|
||||||
|
* "allowedMaxFileSize" instance property on construct.
|
||||||
|
*
|
||||||
|
* @config
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $default_max_file_size = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about the temporary file produced
|
* Information about the temporary file produced
|
||||||
* by the PHP-runtime.
|
* by the PHP-runtime.
|
||||||
@ -360,22 +370,46 @@ class Upload_Validator {
|
|||||||
* @return int Filesize in bytes
|
* @return int Filesize in bytes
|
||||||
*/
|
*/
|
||||||
public function getAllowedMaxFileSize($ext = null) {
|
public function getAllowedMaxFileSize($ext = null) {
|
||||||
|
|
||||||
|
// Check if there is any defined instance max file sizes
|
||||||
|
if (empty($this->allowedMaxFileSize)) {
|
||||||
|
// Set default max file sizes if there isn't
|
||||||
|
$fileSize = Config::inst()->get('Upload_Validator', 'default_max_file_size');
|
||||||
|
if (isset($fileSize)) {
|
||||||
|
$this->setAllowedMaxFileSize($fileSize);
|
||||||
|
} else {
|
||||||
|
// When no default is present, use maximum set by PHP
|
||||||
|
$maxUpload = File::ini2bytes(ini_get('upload_max_filesize'));
|
||||||
|
$maxPost = File::ini2bytes(ini_get('post_max_size'));
|
||||||
|
$this->setAllowedMaxFileSize(min($maxUpload, $maxPost));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$ext = strtolower($ext);
|
$ext = strtolower($ext);
|
||||||
if(isset($ext) && isset($this->allowedMaxFileSize[$ext])) {
|
if ($ext) {
|
||||||
|
if (isset($this->allowedMaxFileSize[$ext])) {
|
||||||
return $this->allowedMaxFileSize[$ext];
|
return $this->allowedMaxFileSize[$ext];
|
||||||
|
}
|
||||||
|
|
||||||
|
$category = File::get_app_category($ext);
|
||||||
|
if ($category && isset($this->allowedMaxFileSize['[' . $category . ']'])) {
|
||||||
|
return $this->allowedMaxFileSize['[' . $category . ']'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return (isset($this->allowedMaxFileSize['*'])) ? $this->allowedMaxFileSize['*'] : false;
|
return (isset($this->allowedMaxFileSize['*'])) ? $this->allowedMaxFileSize['*'] : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set filesize maximums (in bytes).
|
* Set filesize maximums (in bytes or INI format).
|
||||||
* Automatically converts extensions to lowercase
|
* Automatically converts extensions to lowercase
|
||||||
* for easier matching.
|
* for easier matching.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* <code>
|
* <code>
|
||||||
* array('*' => 200, 'jpg' => 1000)
|
* array('*' => 200, 'jpg' => 1000, '[doc]' => '5m')
|
||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
* @param array|int $rules
|
* @param array|int $rules
|
||||||
@ -384,7 +418,22 @@ class Upload_Validator {
|
|||||||
if(is_array($rules) && count($rules)) {
|
if(is_array($rules) && count($rules)) {
|
||||||
// make sure all extensions are lowercase
|
// make sure all extensions are lowercase
|
||||||
$rules = array_change_key_case($rules, CASE_LOWER);
|
$rules = array_change_key_case($rules, CASE_LOWER);
|
||||||
$this->allowedMaxFileSize = $rules;
|
$finalRules = array();
|
||||||
|
$tmpSize = 0;
|
||||||
|
|
||||||
|
foreach ($rules as $rule => $value) {
|
||||||
|
if (is_numeric($value)) {
|
||||||
|
$tmpSize = $value;
|
||||||
|
} else {
|
||||||
|
$tmpSize = File::ini2bytes($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$finalRules[$rule] = (int)$tmpSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->allowedMaxFileSize = $finalRules;
|
||||||
|
} elseif(is_string($rules)) {
|
||||||
|
$this->allowedMaxFileSize['*'] = File::ini2bytes($rules);
|
||||||
} elseif((int) $rules > 0) {
|
} elseif((int) $rules > 0) {
|
||||||
$this->allowedMaxFileSize['*'] = (int)$rules;
|
$this->allowedMaxFileSize['*'] = (int)$rules;
|
||||||
}
|
}
|
||||||
|
@ -84,15 +84,100 @@ class UploadTest extends SapphireTest {
|
|||||||
'error' => UPLOAD_ERR_OK,
|
'error' => UPLOAD_ERR_OK,
|
||||||
);
|
);
|
||||||
|
|
||||||
$v = new UploadTest_Validator();
|
|
||||||
$v->setAllowedMaxFileSize(array('txt' => 10));
|
|
||||||
|
|
||||||
// test upload into default folder
|
// test upload into default folder
|
||||||
$u1 = new Upload();
|
$u1 = new Upload();
|
||||||
|
$v = new UploadTest_Validator();
|
||||||
|
|
||||||
|
$v->setAllowedMaxFileSize(array('txt' => 10));
|
||||||
$u1->setValidator($v);
|
$u1->setValidator($v);
|
||||||
$result = $u1->load($tmpFile);
|
$result = $u1->load($tmpFile);
|
||||||
|
|
||||||
$this->assertFalse($result, 'Load failed because size was too big');
|
$this->assertFalse($result, 'Load failed because size was too big');
|
||||||
|
|
||||||
|
$v->setAllowedMaxFileSize(array('[doc]' => 10));
|
||||||
|
$u1->setValidator($v);
|
||||||
|
$result = $u1->load($tmpFile);
|
||||||
|
$this->assertFalse($result, 'Load failed because size was too big');
|
||||||
|
|
||||||
|
$v->setAllowedMaxFileSize(array('txt' => 200000));
|
||||||
|
$u1->setValidator($v);
|
||||||
|
$result = $u1->load($tmpFile);
|
||||||
|
$this->assertTrue($result, 'Load failed with setting max file size');
|
||||||
|
|
||||||
|
// check max file size set by app category
|
||||||
|
$tmpFileName = 'UploadTest-testUpload.jpg';
|
||||||
|
$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
|
||||||
|
file_put_contents($tmpFilePath, $tmpFileContent . $tmpFileContent);
|
||||||
|
|
||||||
|
$tmpFile = array(
|
||||||
|
'name' => $tmpFileName,
|
||||||
|
'type' => 'image/jpeg',
|
||||||
|
'size' => filesize($tmpFilePath),
|
||||||
|
'tmp_name' => $tmpFilePath,
|
||||||
|
'extension' => 'jpg',
|
||||||
|
'error' => UPLOAD_ERR_OK,
|
||||||
|
);
|
||||||
|
|
||||||
|
$v->setAllowedMaxFileSize(array('[image]' => '40k'));
|
||||||
|
$u1->setValidator($v);
|
||||||
|
$result = $u1->load($tmpFile);
|
||||||
|
$this->assertTrue($result, 'Load failed with setting max file size');
|
||||||
|
|
||||||
|
$v->setAllowedMaxFileSize(array('[image]' => '1k'));
|
||||||
|
$u1->setValidator($v);
|
||||||
|
$result = $u1->load($tmpFile);
|
||||||
|
$this->assertFalse($result, 'Load failed because size was too big');
|
||||||
|
|
||||||
|
$v->setAllowedMaxFileSize(array('[image]' => 1000));
|
||||||
|
$u1->setValidator($v);
|
||||||
|
$result = $u1->load($tmpFile);
|
||||||
|
$this->assertFalse($result, 'Load failed because size was too big');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetAllowedMaxFileSize() {
|
||||||
|
Config::nest();
|
||||||
|
|
||||||
|
// Check the max file size uses the config values
|
||||||
|
$configMaxFileSizes = array(
|
||||||
|
'[image]' => '1k',
|
||||||
|
'txt' => 1000
|
||||||
|
);
|
||||||
|
Config::inst()->update('Upload_Validator', 'default_max_file_size', $configMaxFileSizes);
|
||||||
|
$v = new UploadTest_Validator();
|
||||||
|
|
||||||
|
$retrievedSize = $v->getAllowedMaxFileSize('[image]');
|
||||||
|
$this->assertEquals(1024, $retrievedSize, 'Max file size check on default values failed (config category set check)');
|
||||||
|
|
||||||
|
$retrievedSize = $v->getAllowedMaxFileSize('txt');
|
||||||
|
$this->assertEquals(1000, $retrievedSize, 'Max file size check on default values failed (config extension set check)');
|
||||||
|
|
||||||
|
// Check instance values for max file size
|
||||||
|
$maxFileSizes = array(
|
||||||
|
'[doc]' => 2000,
|
||||||
|
'txt' => '4k'
|
||||||
|
);
|
||||||
|
$v = new UploadTest_Validator();
|
||||||
|
$v->setAllowedMaxFileSize($maxFileSizes);
|
||||||
|
|
||||||
|
$retrievedSize = $v->getAllowedMaxFileSize('[doc]');
|
||||||
|
$this->assertEquals(2000, $retrievedSize, 'Max file size check on instance values failed (instance category set check)');
|
||||||
|
|
||||||
|
// Check that the instance values overwrote the default values
|
||||||
|
// ie. The max file size will not exist for [image]
|
||||||
|
$retrievedSize = $v->getAllowedMaxFileSize('[image]');
|
||||||
|
$this->assertFalse($retrievedSize, 'Max file size check on instance values failed (config overridden check)');
|
||||||
|
|
||||||
|
// Check a category that has not been set before
|
||||||
|
$retrievedSize = $v->getAllowedMaxFileSize('[zip]');
|
||||||
|
$this->assertFalse($retrievedSize, 'Max file size check on instance values failed (category not set check)');
|
||||||
|
|
||||||
|
// Check a file extension that has not been set before
|
||||||
|
$retrievedSize = $v->getAllowedMaxFileSize('mp3');
|
||||||
|
$this->assertFalse($retrievedSize, 'Max file size check on instance values failed (extension not set check)');
|
||||||
|
|
||||||
|
$retrievedSize = $v->getAllowedMaxFileSize('txt');
|
||||||
|
$this->assertEquals(4096, $retrievedSize, 'Max file size check on instance values failed (instance extension set check)');
|
||||||
|
|
||||||
|
Config::unnest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAllowedSizeOnFileWithNoExtension() {
|
public function testAllowedSizeOnFileWithNoExtension() {
|
||||||
|
Loading…
Reference in New Issue
Block a user