Прежде всего, ваш пример кода слепо доверяет клиенту, он принимает любой файл и позволяет выбирать произвольные целевые местоположения, передавая путь в качестве имени файла! Никогда не используйте данные клиента без их проверки / очистки, если доверять дате файла, предоставленной клиентом, это может привести к всевозможным уязвимостям !!!
При этом, как правило, вы либо используете отдельное поле для загрузки файла, или пользовательский тип базы данных, который не преобразует данные при их маршалинге, чтобы впоследствии вы могли преобразовать их вручную. В настоящее время вы, похоже, используете поле для загрузки, которое должно содержать строку в базе данных, поэтому маршаллер попытается преобразовать ввод в строку, и это, конечно, не удастся.
Так, например, переименуйте элемент управления формы с image
на image_file
(в базе данных такого столбца не должно быть), добавьте правильные правила проверки для image_file
, что-то вроде этого, чтобы убедиться, что выгрузка действительна, ie проверьте тип, размер, имя и т. д. c:
$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
]);
А затем выполните загрузку после исправления, ie после проверки и только переместите файл, если проверка прошла успешно!
$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();
$image->moveTo(WWW_ROOT . 'img' . DS . $fileName;);
$user->image = $fileName;
}
if ($this->Users->save($user)) {
// success
} else {
// failure
}
Как только вы поймете, как все работает, вам, вероятно, следует рассмотреть возможность перемещения логики обработки выгрузки c в свой класс таблицы или в поведение ( beforeSave()
Событие / обратный вызов очень популярны для выполнения лога загрузки c) или какой-либо службы.
Вы также можете посмотреть, как существующие плагины обрабатывают до объявления, см., например, https://github.com/FriendsOfCake/awesome-cakephp#user -content-files