Nil*_*ony 0 cakephp cakephp-4.x
我正在尝试在 cakephp 版本 4 中上传文件。
我正在关注这个文档
我在控制器中尝试过
if ($this->request->is('post')) {
$image = $this->request->getData('image');
$fileName = $image->getClientFilename();
$targetPath = WWW_ROOT.'img'.DS.$fileName;
$image->moveTo($targetPath);
$user = $this->Users->patchEntity($user, $this->request->getData()); //line 58
$user->image = $fileName;
$this->Users->save($user);
}
Run Code Online (Sandbox Code Playgroud)
图片上传工作正常,名称也保存在数据库中。但是当发生验证错误时,我得到
Warning (4096): Object of class Laminas\Diactoros\UploadedFile could not be converted to string [CORE\src\Database\Type\StringType.php, line 97]
Run Code Online (Sandbox Code Playgroud)
日志
Cake\Database\Type\StringType::marshal() - CORE\src\Database\Type\StringType.php, line 97
Cake\ORM\Marshaller::Cake\ORM\{closure}() - CORE\src\ORM\Marshaller.php, line 78
Cake\ORM\Marshaller::merge() - CORE\src\ORM\Marshaller.php, line 558
Cake\ORM\Table::patchEntity() - CORE\src\ORM\Table.php, line 2761
App\Controller\UsersController::add() - APP/Controller\UsersController.php, line 58
Cake\Controller\Controller::invokeAction() - CORE\src\Controller\Controller.php, line 524
Cake\Controller\ControllerFactory::invoke() - CORE\src\Controller\ControllerFactory.php, line 79
Cake\Http\BaseApplication::handle() - CORE\src\Http\BaseApplication.php, line 229
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 77
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 77
Cake\Http\Middleware\CsrfProtectionMiddleware::process() - CORE\src\Http\Middleware\CsrfProtectionMiddleware.php, line 132
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 73
Cake\Http\Runner::run() - CORE\src\Http\Runner.php, line 58
Cake\Routing\Middleware\RoutingMiddleware::process() - CORE\src\Routing\Middleware\RoutingMiddleware.php, line 162
Cake\Http\Runner::handle() - CORE\src\Http\Runner.php, line 73
Cake\Routing\Middleware\AssetMiddleware::process() - CORE\src\Routing\Middleware\AssetMiddleware.php, line 68
Run Code Online (Sandbox Code Playgroud)
首先,您的代码示例盲目信任客户端,它接受任何文件,并允许通过传递路径作为文件名来选择任意目标位置!切勿在未验证/清理的情况下使用客户端数据,相信客户端提供的文件日期会导致各种漏洞!!!
话虽如此,通常您要么使用单独的字段进行文件上传,要么使用在编组时不转换数据的自定义数据库类型,以便您可以在之后手动转换它。目前,您似乎使用应该在数据库中保存字符串的上传字段,因此编组器将尝试将输入转换为字符串,这当然会失败。
例如,将表单控件从imageto重命名image_file(数据库中不应该存在这样的列),为 ,添加适当的验证规则image_file,类似于此,以确保上传有效,即检查类型,大小,名称等:
$validator
->notEmptyFile('image_file')
->uploadedFile('image_file', [
'types' => ['image/png'], // only PNG image files
'minSize' => 1024, // Min 1 KB
'maxSize' => 1024 * 1024 // Max 1 MB
])
->add('image_file', 'minImageSize', [
'rule' => ['imageSize', [
// Min 10x10 pixel
'width' => [Validation::COMPARE_GREATER_OR_EQUAL, 10],
'height' => [Validation::COMPARE_GREATER_OR_EQUAL, 10],
]]
])
->add('image_file', 'maxImageSize', [
'rule' => ['imageSize', [
// Max 100x100 pixel
'width' => [Validation::COMPARE_LESS_OR_EQUAL, 100],
'height' => [Validation::COMPARE_LESS_OR_EQUAL, 100],
]]
])
->add('image_file', 'filename', [
'rule' => function (UploadedFileInterface $file) {
// filename must not be a path
$filename = $file->getClientFilename();
if (strcmp(basename($filename), $filename) === 0) {
return true;
}
return false;
}
])
->add('image_file', 'extension', [
'rule' => ['extension', ['png']] // .png file extension only
]);
Run Code Online (Sandbox Code Playgroud)
然后在修补后处理上传,即在验证发生后,只有在验证成功时才移动文件!
$user = $this->Users->patchEntity($user, $this->request->getData());
if (!$user->getErrors()) {
// never trust anything in `$image` if you haven't properly validated it!!!
$image = $this->request->getData('image_file');
$fileName = $image->getClientFilename();
// if you want to take it a step further, drop the user supplied filename
// $fileName = \Cake\Utility\Security::hash($image->getClientFilename(), 'sha1');
// and re-encode the image to remove possible dangerous payloads, meta data, etc
// reEncodeImage($image->getStream());
$image->moveTo(WWW_ROOT . 'img' . DS . $fileName);
$user->image = $fileName;
}
if ($this->Users->save($user)) {
// success
} else {
// failure
}
Run Code Online (Sandbox Code Playgroud)
一旦您掌握了事情的工作原理,您可能应该考虑在您的表类或行为(beforeSave()事件/回调对于执行上传逻辑非常流行)或某种服务中移动上传处理逻辑。
您可能还想查看现有插件如何处理上传,例如参见https://github.com/FriendsOfCake/awesome-cakephp#user-content-files
| 归档时间: |
|
| 查看次数: |
2877 次 |
| 最近记录: |