unlink抛出错误:资源暂时不可用

时间:2022-09-22 13:01:05

Here is the piece of code:

这是一段代码:

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);
}

I am trying to do the following things:

我正在尝试做以下事情:

  1. Get a photo from a URL and save it in a temp folder in my server. This works fine. The image file is created and echoes If file exists: 1 when echo("If file exists: ".file_exists('../storage/temp/image.jpg'));.
  2. 从URL获取照片并将其保存到服务器中的临时文件夹中。这是很好。创建图像文件,并在文件存在时进行回声:1(“如果文件存在:”.file_exists('.. ./storage/temp/image.jpg');
  3. Pass that file to another function that hanldes uploading the file to Amazon s3 bucket. The file gets stored in my s3 bucket.
  4. 将该文件传递到另一个函数,hanldes将该文件上载到Amazon s3 bucket。文件存储在我的s3存储桶中。
  5. Delete the photo stored in the temp folder. This doesn't work! I get an error saying:
  6. 删除存储在temp文件夹中的照片。这并不工作!我得到一个错误的答案:

unlink(../storage/temp/image.jpg): Resource temporarily unavailable

分离(. . /存储/ temp / image.jpg):资源暂时不可用

If I use rename($filename,'../storage/temp/renimage.jpg'); instead of unlink($filename); i get an error:

如果我使用rename($文件名,“. . /存储/ temp / renimage.jpg”);而不是分开($ filename);我得到一个错误:

rename(../storage/temp/image.jpg,../storage/temp/renimage.jpg): The process cannot access the file because it is being used by another process. (code: 32)

这个进程不能访问这个文件,因为它正在被另一个进程使用。(代码:32)

If I remove the function call $photoService->uploadPhoto($filename);, everything works perfectly fine.

如果我删除函数,调用$photoService->uploadPhoto($filename);

If the file is being used by another process, how do I unlink it after the process has been completed and the file is no longer being used by any process? I do not want to use timers.

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

Please help! Thanks in advance.

请帮助!提前谢谢。

4 个解决方案

#1


2  

Just had to deal with a similar Error.

只是要处理类似的错误。

It seems your $photoService is holding on to the image for some reason... Since you didn't share the code of $photoService, my suggestion would be to do something like this (assuming you don't need $photoService anymore):

看来你的$photoService因为某种原因而保留了这张照片……既然你没有分享$photoService的代码,我的建议是做这样的事情(假设你不再需要$photoService):

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

The unset() method will destroy the given variable/object, so it can't "use" (or wharever it does) any files.

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

#2


2  

I sat over this problem for an hour or two, and finally realized that "temporarily unavailable" really means "temporarily".

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

In my case, concurrent PHP scripts access the file, either writing or reading. And when the unlink() process had a poor timing, then the whole thing failed.

在我的例子中,并发的PHP脚本可以访问文件,无论是写还是读。当unlink()进程的时间安排不好时,整个过程就失败了。

The solution was quite simple: Use the (generally not very advisable) @ to prevent the error being shown to the user (sure, one could also stop errors from beinf printed), and then have another try:

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

$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);
}

After solving this issue and pushing my luck further, I could also trigger the "Resource temporarily unavailable" issue with file_put_contents(). Same solution, now everything works fine.

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

If I'm wise enough and/or unlinking fails in the future, I'll replace the @ by ob_start(), so the error message could tell me the exact error.

如果我足够聪明,并且/或取消链接在将来失败,我将用ob_start()替换@,这样错误消息就可以告诉我确切的错误。

#3


0  

I had the same problem. The S3 Client doesn't seem to want to unlock before unlink is being executed. If you extract the contents into a variable and set it as the 'body' in the putObject array:

我也有同样的问题。在执行unlink之前,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'
));

See this answer: How to unlock the file after AWS S3 Helper uploading file?

见此答案:AWS S3助手上传文件后如何解锁文件?

#4


-2  

The unlink method return bool value, so you can build a cycle, with some wait() and retries limit to wait for your processes to complete.

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

Additionally put "@" on the unlink, to hide the access error.

另外在unlink上加上“@”,以隐藏访问错误。

Throw another error/exception if retries count reached.

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

#1


2  

Just had to deal with a similar Error.

只是要处理类似的错误。

It seems your $photoService is holding on to the image for some reason... Since you didn't share the code of $photoService, my suggestion would be to do something like this (assuming you don't need $photoService anymore):

看来你的$photoService因为某种原因而保留了这张照片……既然你没有分享$photoService的代码,我的建议是做这样的事情(假设你不再需要$photoService):

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

The unset() method will destroy the given variable/object, so it can't "use" (or wharever it does) any files.

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

#2


2  

I sat over this problem for an hour or two, and finally realized that "temporarily unavailable" really means "temporarily".

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

In my case, concurrent PHP scripts access the file, either writing or reading. And when the unlink() process had a poor timing, then the whole thing failed.

在我的例子中,并发的PHP脚本可以访问文件,无论是写还是读。当unlink()进程的时间安排不好时,整个过程就失败了。

The solution was quite simple: Use the (generally not very advisable) @ to prevent the error being shown to the user (sure, one could also stop errors from beinf printed), and then have another try:

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

$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);
}

After solving this issue and pushing my luck further, I could also trigger the "Resource temporarily unavailable" issue with file_put_contents(). Same solution, now everything works fine.

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

If I'm wise enough and/or unlinking fails in the future, I'll replace the @ by ob_start(), so the error message could tell me the exact error.

如果我足够聪明,并且/或取消链接在将来失败,我将用ob_start()替换@,这样错误消息就可以告诉我确切的错误。

#3


0  

I had the same problem. The S3 Client doesn't seem to want to unlock before unlink is being executed. If you extract the contents into a variable and set it as the 'body' in the putObject array:

我也有同样的问题。在执行unlink之前,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'
));

See this answer: How to unlock the file after AWS S3 Helper uploading file?

见此答案:AWS S3助手上传文件后如何解锁文件?

#4


-2  

The unlink method return bool value, so you can build a cycle, with some wait() and retries limit to wait for your processes to complete.

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

Additionally put "@" on the unlink, to hide the access error.

另外在unlink上加上“@”,以隐藏访问错误。

Throw another error/exception if retries count reached.

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