mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
FEATURE - Added maximum upload file size by type
This support is on both an instance level and a global default level.
This commit is contained in:
parent
43f49e8434
commit
ae8dbe309b
@ -148,6 +148,16 @@ NOTE: this only sets the configuration for your UploadField, this does NOT chang
|
||||
$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
|
||||
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 `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.
|
||||
|
||||
```yaml
|
||||
|
@ -305,6 +305,16 @@ class Upload extends Controller {
|
||||
*/
|
||||
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
|
||||
* by the PHP-runtime.
|
||||
@ -360,22 +370,46 @@ class Upload_Validator {
|
||||
* @return int Filesize in bytes
|
||||
*/
|
||||
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);
|
||||
if(isset($ext) && isset($this->allowedMaxFileSize[$ext])) {
|
||||
if ($ext) {
|
||||
if (isset($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 {
|
||||
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
|
||||
* for easier matching.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* array('*' => 200, 'jpg' => 1000)
|
||||
* array('*' => 200, 'jpg' => 1000, '[doc]' => '5m')
|
||||
* </code>
|
||||
*
|
||||
* @param array|int $rules
|
||||
@ -384,7 +418,22 @@ class Upload_Validator {
|
||||
if(is_array($rules) && count($rules)) {
|
||||
// make sure all extensions are lowercase
|
||||
$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) {
|
||||
$this->allowedMaxFileSize['*'] = (int)$rules;
|
||||
}
|
||||
|
@ -84,15 +84,100 @@ class UploadTest extends SapphireTest {
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
);
|
||||
|
||||
$v = new UploadTest_Validator();
|
||||
$v->setAllowedMaxFileSize(array('txt' => 10));
|
||||
|
||||
// test upload into default folder
|
||||
$u1 = new Upload();
|
||||
$v = new UploadTest_Validator();
|
||||
|
||||
$v->setAllowedMaxFileSize(array('txt' => 10));
|
||||
$u1->setValidator($v);
|
||||
$result = $u1->load($tmpFile);
|
||||
|
||||
$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() {
|
||||
|
Loading…
Reference in New Issue
Block a user