【问题标题】:php - unlink throws error: Resource temporarily unavailablephp - 取消链接抛出错误:资源暂时不可用
【发布时间】:2017-08-23 04:39:43
【问题描述】:

这是一段代码:

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. 删除临时文件夹中存储的照片。 这不起作用!我收到一条错误消息:

unlink(../storage/temp/image.jpg):资源暂时不可用

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

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

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

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

请帮忙!提前致谢。

【问题讨论】:

  • 作为旁注,您应该使用绝对文件路径而不是相对文件路径。在文件路径中使用 $_SERVER['DOCUMENT_ROOT'] 而不是 ../
  • 不要完整阅读,但在echo("If file exists: ".file_exists($filename)); php.net/manual/en/function.clearstatcache.php 之前使用clearstatcache(),也许$photoService->uploadPhoto 在你之前取消链接。
  • 使用唯一名称而不是 image.jpg 会不会更好,也许不同。请求尝试处理同一个文件。
  • @Martin 不是在unlink 之后,而是在file_exists 之前,谁知道uploadPhoto 做了什么。 ;-) 我粘贴了链接,所以 OP 可以阅读它,获取它。
  • @JustOnUnderMillions,是的。我在我的实际代码中使用了一个唯一的名称生成器。上面给出的代码sn-p是为了贴在这里。

标签: php amazon-s3 unlink


【解决方案1】:

最简单的解决方案:

gc_collect_cycles();
unlink($file);

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

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

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

:)

【讨论】:

    【解决方案2】:

    只需要处理类似的错误。

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

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

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

    【讨论】:

    • 请注意,如果您运行的是 Linux 或 MacOS 或 *BSD,则不必在删除之前关闭所有句柄。但如果您在 MS Windows 上运行 php,那么您需要先关闭所有句柄
    【解决方案3】:

    我在这个问题上坐了一两个小时,终于意识到“暂时不可用”的真正意思是“暂时”。

    在我的例子中,并发 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(),因此错误消息可以告诉我确切的错误。

    【讨论】:

      【解决方案4】:

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

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

      看到这个答案:How to unlock the file after AWS S3 Helper uploading file?

      【讨论】:

        【解决方案5】:

        unlink 方法返回 bool 值,因此您可以构建一个循环,其中包含一些 wait() 和 retries 限制以等待您的进程完成。

        在取消链接上加“@”,隐藏访问错误。

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

        【讨论】:

        • 这些都是旨在隐藏症状而不是解决问题的糟糕解决方案。不要不要使用@错误抑制和等待只会占用你的服务器进程(当PHP等待它循环CPU电源时,它不会暂停处理)
        • @Martin,我同意。不建议使用@
        • 我听到这个笑了。如果有错误只是压制它!哈哈!
        • 当然不建议这样做,当然有更好的解决方案可以在更高的 php 版本上捕获这些警告。不知道你们为什么坚持这个特定的部分,哈哈。你可以随心所欲地笑:) 很高兴看到我把别人的一天做得更好。
        猜你喜欢
        • 1970-01-01
        • 2010-11-21
        • 2018-02-08
        • 1970-01-01
        • 1970-01-01
        • 2017-02-10
        • 2023-03-03
        • 1970-01-01
        • 2016-11-19
        相关资源
        最近更新 更多