【问题标题】:delete file from the server after download in php在php中下载后从服务器中删除文件
【发布时间】:2013-06-26 12:04:32
【问题描述】:

我正在使用 php 下载文件,我希望文件在成功完成下载后自动从服务器中删除。我在 php 中使用此代码。

$fullPath = 'folder_name/download.txt';

if ($fd = fopen ($fullPath, "r")) {
    $fsize = filesize($fullPath);
    $path_parts = pathinfo($fullPath);
    $ext = strtolower($path_parts["extension"]);

    header("Content-type: application/octet-stream");
    header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
    header("Content-length: $fsize");
    header("Cache-control: private"); //use this to open files directly
    $fd = fopen ($fullPath, "r");
    while(!feof($fd)) {
        $buffer = fread($fd, 2048);
        echo $buffer;
    }
    fclose ($fd);

}

unlink($fullPath);

您可以在下载后的代码中看到我取消了文件链接。但如果我这样做,损坏的文件就会被下载。因为有时文件在完全下载之前就被删除了。无论如何在php中知道客户端成功下载文件然后我可以删除它?任何想法都将受到高度赞赏。

【问题讨论】:

  • 没有什么好方法可以告诉您下载已完成。如果您要下载的文件不是很大,那么您可以做的最好的事情是通过电子邮件发送它们并立即删除它们。
  • 你能做一个文件大小检查并比较大小是否相同就完成了吗?
  • 文件删除比文件下载快

标签: php


【解决方案1】:

据我所知,您不能使用服务器端 PHP 来检测客户端的下载是否已完成。 ignore_user_abort() 似乎是您问题的答案(见下文),否则您可以在设定的时间后删除文件。

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

在 Stackoverflow 上相关/重复:

【讨论】:

    【解决方案2】:

    如果您真的在下载(而不是上传,就像您帖子中的代码所建议的那样),您可能对专门用于创建文件的 tmpfile 功能感兴趣,该功能将立即被删除关闭其描述符。

    【讨论】:

    • 这真的很简单,因为他可以打开两个文件 - 然后使用 stream_copy_to_stream - 删除旧文件并读取 tmp 文件 - 但这会破坏部分下载:)
    【解决方案3】:

    无法知道用户何时使用 PHP 完成下载文件,我会在请求的 n 秒后使用队列系统删除文件:

    How to Build a PHP Queue System

    【讨论】:

    • 这似乎不是真的。为什么 PHP 不能读取服务器日志并记录文件传输的时间。只需总结所有 2xx 请求的传输大小,如果等于或大于(HTTP 标头开销),则文件已下载。
    【解决方案4】:

    在服务器和客户端检查文件的哈希码... 您可以使用 javascript(How to calculate md5 hash of a file using javascript) 检查哈希码,将其发送到服务器,然后检查服务器上是否相同...

    【讨论】:

      【解决方案5】:

      检查请求,如果设置了Range HTTP 头,客户端正在分片下载文件,它想一次只下载一小部分数据(例如:Range: bytes=500-999)。通常这是由网络服务器自动处理的,但在这种情况下,您必须处理它并只发送请求的范围。将进度存储在会话中,仅当客户端下载所有片段时才拒绝访问。

      【讨论】:

        【解决方案6】:

        这对于大文件可能有点问题,但对于快速连接的小文件,我使用它没有问题。

        <?php
         ### Check the CREATE FILE has been set and the file exists
        if(isset($_POST['create_file']) && file_exists($file_name)):
        ### Download Speed (in KB)
        $dls = 50;
        ### Delay time (in seconds) added to download time 
        $delay = 5; 
        ## calculates estimated download time
        $timer = round(filesize($file_name) / 1024 / $dls + $delay); 
        ###Calculates file size in kb divides by download speed + 5 ?>
        
        <iframe width="0" height="0" frameborder="0" src="<?php echo $file_name;?>"></iframe>
        <h2>Please Wait, Your Download will complete in: <span id="logout-timer"></span></h2> 
        

        使用文件值 ?f=$file_name 重定向到 SELF

        <script>setTimeout(function(){ window.location = "<?php echo $_SERVER['PHP_SELF']?>?f=<?php echo $file_name;?>";},<?php echo $timer;?>000);</script>
        

        删除文件

             <?php 
         endif;
        if (isset($_GET['f'])):
            unlink($_GET['f']);
            ### removes GET value and returns to page's original url
            echo "<script> location.replace('".$_SERVER['PHP_SELF']."')</script>"; 
            endif;?>
        

        为每个文件设置的下载计时器(以 var 秒为单位)

        <script>
        var seconds=<?php echo $timer;?>;function secondPassed(){var a=Math.round((seconds-30)/60);var b=seconds%60;if(b<10){b="0"+b}document.getElementById('logout-timer').innerHTML=a+":"+b;if(seconds==0){clearInterval(countdownTimer);document.getElementById('logout-timer').innerHTML="Timer"}else{seconds--}}var countdownTimer=setInterval('secondPassed()',1000);
        </script>
        

        【讨论】:

          【解决方案7】:

          不确定它是否适用于几乎所有情况,但请尝试 sleep(10);将文件删除延迟一段时间。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-01-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-18
            相关资源
            最近更新 更多