【问题标题】:Deleting a file after user download it用户下载后删除文件
【发布时间】:2010-04-14 23:08:18
【问题描述】:

我正在使用它向用户发送文件

header('Content-type:  application/zip');
header('Content-Length: ' . filesize($file));
header('Content-Disposition: attachment; filename="file.zip"');
readfile($file);

我想在用户下载后删除这个文件,我该怎么做?

编辑:我的场景是这样的,当用户点击下载按钮时,我的脚本将创建一个临时 zip 文件并用户下载它,然后该临时 zip 文件将被删除。

EDIT2:OK 最好的方法似乎是运行一个每小时清理一次临时文件的 cron 作业。

EDIT3:我用unlink 测试了我的脚本,除非用户取消下载,否则它可以工作。如果用户取消下载,zip 文件将保留在服务器上。所以现在就足够了。 :)

EDIT4:哇! connection_aborted() 成功了!

ignore_user_abort(true);
if (connection_aborted()) {
    unlink($f);
}

即使用户取消下载,此文件也会删除。

【问题讨论】:

标签: php


【解决方案1】:
unlink($filename);

这将删除文件。

它需要与ignore_user_abort()Docs结合,这样unlink即使用户取消下载仍然会执行。

ignore_user_abort(true);

...

unlink($f);

【讨论】:

  • 您最好不要直接从磁盘上提供文件,而是使用一个唯一的 URL,您可以在下载请求后禁用该 URL。
  • 我的场景是这样的,当用户点击下载按钮时,我的脚本会创建一个临时文件。 zip 文件和用户下载它然后临时 zip 文件将被删除
  • @Ahmet vardar:为什么不直接回显 Zip 的内容?
  • @Billy:因为如果我这样做,用户将无法下载导航
  • @George Edison:*Bill 关闭简历支持。加速器不高兴。比尔很高兴:D
【解决方案2】:

我总是使用以下解决方案,使用register_shutdown_function

register_shutdown_function('unlink', $file);

【讨论】:

  • 非常适合我在函数运行时文件需要存在的情况,但是一旦脚本完全完成,它就会成功删除临时文件。
  • ignore_user_abort(true); 下表现最好,恕我直言应该被接受
  • 这个解决方案解决了我的问题,即调用 ob_end_flush() 似乎结束了脚本的执行(即使在下一行调用了取消链接)。
【解决方案3】:

没有任何正确的方法来检测用户是否完全下载了文件。
所以最好的方法是在一段时间不活动后删除文件。

【讨论】:

  • 我认为最好设置一个 Cron 作业以在一段时间后删除文件,比如在文件启动下载 5 分钟后。 (假设下载时间不超过 5 分钟)。
【解决方案4】:

connection_aborted() 从来没有为我工作过。 尽管ob_clean() 完全按照它应该的方式工作。希望这对其他人也有帮助

header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $file . '"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
ob_clean();
flush();
if (readfile($file))
{
  unlink($file);
}

【讨论】:

  • connection_aborted() 对我不起作用,但这成功了
  • @Sebi readfile() 将文件发送到浏览器
  • 好的,但是这篇文章的创建者使用了不正确的 HTTP 标头。 readfile 不考虑字节范围,如果readfile 返回,则假设整个文件已传输给用户也不安全。 chunked 没有 Accept-Ranges 的编码将是一个更好的选择,除非正在进行一些 Range Header 处理。
【解决方案5】:

我找不到适合我的东西,所以我想出了这个,它似乎对我很有效:

header('Content-type: application/zip'); //this could be a different header 
header('Content-Disposition: attachment; filename="'.$zipName.'"');

ignore_user_abort(true);

$context = stream_context_create();
$file = fopen($zipName, 'rb', FALSE, $context);
while(!feof($file))
{
    echo stream_get_contents($file, 2014);
}
fclose($file);
flush();
if (file_exists($zipName)) {
    unlink( $zipName );
}

希望对大家有所帮助

【讨论】:

    【解决方案6】:

    我的一个网站也有非常相似的功能。这就像在/取消下载后删除随机创建的文件夹和 zip 文件一样。我试着在这里解释一下,可能有人觉得它有用。

    skin.php:
    此页面包含下载链接,例如“http://mysite.com/downoload/bluetheme”

    .htaccess:
    我在 htaccess 文件中有以下规则将下载请求重定向到 php 文件。 [下载.php]。

    RewriteRule ^download/([A-Za-z0-9]+)$ download.php?file=$1 [L]
    

    下载.php:

    include "class.snippets.php";
    $sn=new snippets();
    $theme=$_GET['file'];
    $file=$sn->create_zip($theme);
    $path="skins/tmp/$file/$file.zip";
    $config_file="skins/tmp/$file/xconfig.php";
    $dir="skins/tmp/$file";
    
    $file.=".zip";
    header("Content-type: application/zip");
    header("Content-Disposition: attachment; filename=$file");
    header("Pragma: no-cache");
    header("Expires: 0");
    readfile($path);
    
    //remove file after download  
    unlink($path);
    unlink($config_file);
    rmdir($dir);
    

    so on request download.php 将使用 sn-ps 类创建具有随机名称的目录。在目录中,它将创建一个 zip 文件。下载/取消请求后,所有文件和目录都将被删除。

    【讨论】:

    • 如果用户在readfile()函数完成之前取消下载或关闭浏览器,你能保证脚本执行不会终止导致unlink()永远不会被调用吗?
    【解决方案7】:

    对于那些面临“文件开头的额外字节”问题的人,我建议在 readfile 之前添加缓冲区清理功能,如本文所述:

    https://stackoverflow.com/a/51083411/16381972

    @ob_start('');  //@ supresses a warning  
    //header entries
    ob_end_clean();
    ob_clean();
    readfile($file);
    

    【讨论】:

      猜你喜欢
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-13
      • 1970-01-01
      • 2015-12-19
      • 2018-06-18
      相关资源
      最近更新 更多