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

php-取消链接引发错误:资源暂时不可用,php,amazon-s3,unlink,Php,Amazon S3,Unlink,下面是一段代码: 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_

下面是一段代码:

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);
}
我正在尝试做以下事情:

  • 从URL获取照片并将其保存在我的服务器的临时文件夹中。这个很好用。创建图像文件并在
    回显时回显
    如果文件存在:1
    回显(“如果文件存在:”.file_存在(“../storage/temp/image.jpg”)
  • 将该文件传递给另一个函数,hanldes将该文件上传到amazons3 bucket。该文件存储在我的s3存储桶中
  • 删除临时文件夹中存储的照片这不起作用我收到一个错误,说:
  • 取消链接(../storage/temp/image.jpg):资源暂时不可用

    如果我使用
    rename($filename,../storage/temp/renimage.jpg')而不是
    取消链接($filename)我得到一个错误:

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

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

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


    请帮忙!提前感谢。

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

    另外,在取消链接上添加“@”,以隐藏访问错误


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

    必须处理类似的错误

    您的
    $photoService
    似乎出于某种原因保留了图像。。。 由于您没有共享
    $photoService
    的代码,我的建议是这样做(假设您不再需要
    $photoService
    ):


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

    我也遇到了同样的问题。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'
    ));
    

    看到这个答案:

    我花了一两个小时思考这个问题,最后意识到“暂时不可用”实际上是指“暂时”

    在我的例子中,并发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);
    }
    
    $gone=false;
    对于($trial=0;$trial最简单的解决方案:

    gc_collect_cycles();
    unlink($file);
    
    这是为我做的! 在将文件上传到AmazonS3之后,我就可以直接删除服务器上的文件

    请看这里:

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


    :)

    作为旁注,您应该使用绝对文件路径而不是相对文件路径。在文件路径中使用
    $\u服务器['DOCUMENT\u ROOT']
    ,而不是
    。/
    不要完全读取它,而是在
    回显(“如果文件存在:.file\u存在($filename))之前使用
    clearstatcache()
    也许
    $photoService->uploadPhoto
    会在您之前取消链接。使用唯一的名称而不是
    图像不是更好吗。jpg
    ,也许不同的请求会尝试在同一个文件上工作。@Martin不是在
    取消链接之后,而是在
    文件存在之前,谁知道
    uploadPhoto
    会做什么。;-)我粘贴了链接,这样OP就可以阅读它,从而得到它。@justonundermillion,是的。我在实际代码中使用了唯一的名称生成器。上面给出的代码片段是为了在这里发布。这些都是旨在隐藏症状而不是解决问题的糟糕解决方案。不要使用
    @
    错误抑制和等待只会占用服务器进程(当PHP等待时,它会循环CPU电源,不会暂停处理)@Martin,我同意。不建议使用
    @
    。请注意,如果您运行的是Linux或MacOS或*BSD,则不必在删除它之前关闭所有句柄。。但如果您在MS Windows上运行php,则需要首先关闭所有句柄
    gc_collect_cycles();
    unlink($file);