Ci4图片上传与处理报错:finfo_file(/tmp/phpSrVWUZ): failed to open stream: No such file or directory 问题求助
问题分析
你碰到的两个错误其实是连锁反应:
The uploaded file has already been moved:当你调用store()方法时,已经把服务器临时目录里的上传文件移到了WRITEPATH.'uploads/'目录,这时原上传文件对象(比如你代码里的$update_post)指向的临时文件已经不存在了,再调用move()自然会报错。finfo_file(/tmp/phpSrVWUZ): failed to open stream: No such file or directory:同样的道理,临时文件被store()移走后,后续再通过原文件对象操作时,系统找不到原临时文件,导致finfo读取失败。
解决方案
我给你两种可行的调整方案,根据你的需求选就行:
方案一:直接处理临时文件再移到Public目录(推荐)
这个流程更简洁,跳过中间临时目录的存储,直接操作服务器临时文件,处理完成后再移动到目标目录:
// 获取上传文件对象 $uploadedFile = $this->request->getFile('dh_site_logo'); // 先验证文件是否有效,避免无效文件导致后续报错 if (!$uploadedFile->isValid()) { throw new \RuntimeException($uploadedFile->getErrorString().'('.$uploadedFile->getError().')'); } // 对服务器临时文件进行裁剪处理,直接覆盖原临时文件 service('image') ->withFile($uploadedFile->getTempName()) ->fit(250, 150, 'center') ->save($uploadedFile->getTempName()); // 将处理后的临时文件移动到public目录,指定新文件名 $publicPath = ROOTPATH . 'public'; $newFileName = 'site_logo.' . $uploadedFile->getExtension(); $uploadedFile->move($publicPath, $newFileName, true);
方案二:先存到临时目录处理,再移到Public目录
如果你坚持要保留writable/uploads的临时处理文件,可以用文件系统函数来移动,而不是复用原上传对象的move()方法:
$uploadedFile = $this->request->getFile('dh_site_logo'); if (!$uploadedFile->isValid()) { throw new \RuntimeException($uploadedFile->getErrorString().'('.$uploadedFile->getError().')'); } // 先把文件存到writable/uploads目录,拿到相对路径 $tempPath = $uploadedFile->store(); $tempFilePath = WRITEPATH . 'uploads/' . $tempPath; // 对临时目录里的文件进行裁剪 service('image') ->withFile($tempFilePath) ->fit(250, 150, 'center') ->save($tempFilePath); // 用文件系统函数把处理后的文件移到public目录,不要用原上传对象的move() $publicPath = ROOTPATH . 'public'; $newFileName = 'site_logo.' . $uploadedFile->getExtension(); rename($tempFilePath, $publicPath . '/' . $newFileName);
关键注意点
- 上传文件对象的
store()和move()方法本质都是移动服务器临时文件,同一个对象只能调用其中一个方法一次,重复调用必然会触发文件已移动的错误。 - 处理文件前一定要调用
isValid()验证,这能帮你提前拦截上传失败的情况(比如文件过大、格式不允许等)。
内容的提问来源于stack exchange,提问作者spreaderman
相关产品推荐
相关产品推荐

