我正在使用Symfony 2.3来保存由表单POST上传的文件。
这是我在控制器中使用的代码:
move_uploaded_file("/tmp/phpBM9kw8", "/home2/divine/Symfony/src/App/Bundle/Resources/public/files/book.pdf");
在水下,Symfony执行此代码来移动文件:
"Could not move the file "/tmp/phpBM9kw8" to "/home2/divine/Symfony/src/App/Bundle/Resources/public/files/book.pdf"
(move_uploaded_file() expects parameter 2 to be valid path, object given)"
公共目录有777个权限。
这是我得到的错误:
// Class: Symfony\Component\HttpFoundation\File\UploadedFile
$target = $this->getTargetFile($directory, $name);
if (!@move_uploaded_file($this->getPathname(), $target)) {
// etc...
我正在使用PHP 5.3。
更新
这是执行move_uploaded_file()的代码剪切:
protected function getTargetFile($directory, $name = null) {
// Some error handling here...
$target = $directory.DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name));
return new File($target, false);
}
$ target“变量在这里创建:
/**
* Returns the path to the file as a string
* @link http://php.net/manual/en/splfileinfo.tostring.php
* @return string the path to the file.
* @since 5.1.2
*/
public function __toString () {}
$ target变量就是File类。它有一个__toString()方法,继承自SplFileInfo:
{{1}}
但不知怎的,__toString方法无效。
答案 0 :(得分:3)
但不知何故__toString方法无法正常工作
它是“魔术方法”之一,当在字符串上下文中使用对象时会自动调用它 - 例如,如果你有'foo' . $object
。
但我不认为假设在这种情况下工作。因为PHP是松散类型的,所以你可以将任何传递给move_uploaded_file
。此时不会自动转换为字符串。然后在内部,该函数仅检查参数是否为字符串,但不尝试将其转换为一个 - 因为这没有意义,它可能是任何类型的对象,并且无法判断调用__toString是否会产生有效的文件路径。
您现在可能想知道,为什么在错误消息中我们会看到路径:
无法将文件“/ tmp / phpBM9kw8”移动到“/home2/divine/Symfony/src/App/Bundle/Resources/public/files/book.pdf”
我的猜测是,当组装该错误消息时,会进行字符串连接,以便在此特定点调用__toString。
如果您愿意修改Symfony源代码,我认为这应该是一个简单的解决方案,如果您只是更改此行
if (!@move_uploaded_file($this->getPathname(), $target)) {
到
if (!@move_uploaded_file($this->getPathname(), ''.$target)) {
- 然后再次出现这种情况,其中将调用__toString,因为该对象通过将其与字符串(空字符串)连接而转移到字符串上下文中,因为我们不想篡改结果值。 )
当然,直接修改框架文件并不是处理此问题的最佳方法 - 在下次更新后,我们的更改可能会再次丢失。我建议您检查Symfony bugtracker(他们应该有类似的东西),看看这是否已经存在已知问题,是否存在官方补丁文件;并以其他方式将其报告为错误,以便可以在将来的版本中修复它。