取消链接引发错误:资源暂时不可用



这是一段代码:

public function uploadPhoto(){
$filename = '../storage/temp/image.jpg';  
file_put_contents($filename,file_get_contents('http://example.com/image.jpg'));
$photoService->uploadPhoto($filename);
echo("If file exists: ".file_exists($filename));
unlink($filename);
}

我正在尝试做以下事情:

  1. 从 URL 获取照片并将其保存在我的服务器的临时文件夹中。这工作正常。将创建图像文件,并在echo("If file exists: ".file_exists('../storage/temp/image.jpg'));时回显If file exists: 1
  2. 该文件传递给另一个函数,该函数需要将文件上传到 Amazon s3 存储桶。该文件存储在我的 s3 存储桶中。
  3. 删除存储在临时文件夹中的照片。这不行!我收到一个错误,说:

取消链接(../storage/temp/image.jpg):资源暂时不可用

如果我使用rename($filename,'../storage/temp/renimage.jpg');而不是unlink($filename);我会收到错误:

重命名(../storage/temp/image.jpg,../storage/temp/renimage.jpg):进程无法访问该文件,因为它正被另一个进程使用。(代码:32)

如果我删除函数调用$photoService->uploadPhoto($filename);,一切正常。

如果该文件正由另一个进程使用,如何在该进程完成且该文件不再被任何进程使用后取消链接?我不想使用计时器。

请帮忙!提前谢谢。

最简单的解决方案:

gc_collect_cycles();
unlink($file);

为我做! 将文件上传到 amazon S3 后,它允许我立即删除服务器上的文件。

看这里: https://github.com/aws/aws-sdk-php/issues/841

GuzzleHttp\Stream 对象保留资源句柄,直到其 调用__destruct方法。通常,这意味着一旦流超出范围,资源就会被释放,但有时,取决于 在 PHP 版本以及脚本是否尚未填充垃圾 收集器的缓冲区,垃圾回收可以延迟。 gc_collect_cycles将强制收集器运行并调用__destruct 在所有无法访问的流对象上。

:)

只需要处理类似的错误。

看来你的$photoService出于某种原因坚持了这个形象...... 由于您没有共享$photoService的代码,我的建议是做这样的事情(假设您不再需要$photoService):

[...]
echo("If file exists: ".file_exists($filename));
unset($photoService);
unlink($filename);
}

unset()方法将销毁给定的变量/对象,因此它不能"使用"(或使用)任何文件。

我在这个问题上坐了一两个小时,终于意识到"暂时不可用"实际上意味着"暂时"。

就我而言,并发PHP脚本访问文件,无论是写入还是读取。当unlink()过程时机不佳时,整个事情就失败了。

解决方案非常简单:使用(通常不太可取的)@来防止向用户显示错误(当然,也可以阻止错误打印),然后再试一次:

$gone = false;
for ($trial=0; $trial<10; $trial++) {
if ($gone = @unlink($filename)) {
break;
}
// Wait a short time
usleep(250000);
// Maybe a concurrent script has deleted the file in the meantime
clearstatcache();
if (!file_exists($filename)) {
$gone = true;
break;
}
}
if (!$gone) {
trigger_error('Warning: Could not delete file '.htmlspecialchars($filename), E_USER_WARNING);
}

在解决了这个问题并进一步推动我的运气之后,我还可以用file_put_contents()触发"资源暂时不可用"问题。相同的解决方案,现在一切正常。

如果我足够聪明和/或将来取消链接失败,我会用ob_start()替换@,因此错误消息可以告诉我确切的错误。

我遇到了同样的问题。S3 客户端似乎不想在执行取消链接之前解锁。如果将内容提取到变量中并将其设置为 putObject 数组中的"body":

$fileContent = file_get_contents($filepath);
$result = $s3->putObject(array(
'Bucket'       => $bucket,
'Key'          => $folderPath,
'Body'         => $fileContent,
//'SourceFile'   => $filepath,
'ContentType'  => 'text/csv',
'ACL'          => 'public-read'
));

请参阅此答案:如何在 AWS S3 帮助程序上传文件后解锁文件?

unlink 方法返回布尔值,因此您可以构建一个循环,并限制一些 wait() 和重试限制以等待进程完成。

另外在取消链接上加上"@",以隐藏访问错误。

如果达到重试计数,则引发另一个错误/异常。

最新更新