php-取消链接抛出错误:资源暂时不可用

inn6fuwd  于 2022-12-25  发布在  PHP
关注(0)|答案(5)|浏览(133)

下面是这段代码:

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.从一个网址获取一张照片,并将其保存在我服务器的临时文件夹中。这工作得很好。图像文件被创建,并在echo("If file exists: ".file_exists('../storage/temp/image.jpg'));时回显If file exists: 1
1.将该文件传递给另一个函数,该函数负责将文件上传到Amazon S3 Bucket。该文件将存储在我的S3 Bucket中。
1.删除存储在临时文件夹中的照片。**这不起作用!**我收到一个错误消息:
取消链接(../storage/temp/image.jpg):资源暂时不可用
如果我使用rename($filename,'../storage/temp/renimage.jpg');而不是unlink($filename);,我会得到一个错误:
重命名(../storage/temp/image.jpg,../存储/临时/重命名图像. jpg):进程无法访问该文件,因为其他进程正在使用该文件。(代码:三十二)
如果我删除函数调用$photoService->uploadPhoto($filename);,那么一切都将运行良好。
如果该文件正被另一个进程使用,如何在该进程完成且该文件不再被任何进程使用后取消链接?我不想使用计时器。
请帮帮忙!先谢了。

zwghvu4y

zwghvu4y1#

最简单的解决方案:

gc_collect_cycles();
unlink($file);

为我做的!直接在上传文件到亚马逊S3后,它允许我删除服务器上的文件。
参见此处:https://github.com/aws/aws-sdk-php/issues/841
GuzzleHttp\Stream对象保留一个资源句柄,直到调用其__destruct方法。通常,这意味着一旦流福尔斯作用域,资源就会被释放,但有时候,根据PHP版本以及脚本是否已经填充了垃圾收集器的缓冲区,垃圾收集可以延迟。gc_collect_cycles将强制收集器运行并对所有无法到达的流对象调用__destruct。
:)

7fhtutme

7fhtutme2#

只是不得不处理一个类似的错误。
看起来您的$photoService由于某种原因保留了映像......由于您没有共享$photoService的代码,我的建议是执行以下操作(假设您不再需要$photoService):

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

unset()方法将销毁给定的变量/对象,因此它不能“使用”(或无论它做什么)任何文件。

baubqpgj

baubqpgj3#

我对这个问题坐了一两个小时,最后才意识到“暂时不能用”确实是“暂时”的意思。
在我的例子中,并发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()替换@,这样错误消息就可以告诉我确切的错误。

4urapxun

4urapxun4#

我遇到了同样的问题。S3客户端似乎不想在执行unlink之前解锁。如果您将内容提取到一个变量中,并将其设置为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 Helper上传文件后如何解锁文件?

h5qlskok

h5qlskok5#

unlink方法返回bool值,因此您可以构建一个循环,使用一些wait()和retries限制来等待您的进程完成。
另外,在取消链接上加上“@”,以隐藏访问错误。
如果达到重试次数,则引发另一个错误/异常。

相关问题