创建临时文件并自动删除

时间:2009-11-22 16:39:40

标签: php temporary-files

我正在编写一个反级的下载脚本,我的计划是创建一个临时文件,该文件由会话ID命名,然后在会话到期后,该文件将被自动删除。可能吗 ?你能给我一些如何在PHP中做到这一点的技巧吗?

非常感谢您的回复

7 个答案:

答案 0 :(得分:11)

PHP具有该名称tmpfile的函数。它创建一个临时文件并返回一个资源。资源可以像任何其他资源一样使用。

E.g。手册中的例子:

<?php
$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
echo fread($temp, 1024);
fclose($temp); // this removes the file
?>

关闭时(使用fclose())或脚本结束时自动删除文件。您可以在资源上使用任何文件功能。你可以找到这些here。希望这会对你有帮助吗?

另一种解决方案是以常规方式创建文件,并使用cronjob定期检查会话是否过期。到期日期和其他会话数据可以存储在数据库中。使用该脚本查询该数据并确定会话是否已过期。如果是这样,请从磁盘中物理删除它。确保每小时左右运行一次脚本(取决于你的超时)。

答案 1 :(得分:10)

因此我们有一个或多个可供下载的文件。为每个下载请求创建临时文件不是一个好主意。为每个文件创建symlink()是一个更好的主意。这将节省大量磁盘空间并降低服务器负载。

在用户会话之后命名符号链接是一个不错的主意。更好的想法是生成随机符号链接名称&amp;与会话关联,因此脚本可以处理每个会话的多个下载。您可以使用session_set_save_handler()link)并注册一个自定义read函数来检查过期的会话,并在会话过期时删除符号链接。

答案 2 :(得分:3)

你能更深入地解释一下你的问题吗?因为我没有看到为什么不使用$_SESSION的原因。 $_SESSION中的数据存储在服务器端的文件中(请参阅 http://php.net/session.save-path)BTW。至少默认情况下。 ; - )

答案 3 :(得分:2)

我建议你不要先复制文件。我会执行以下操作:当用户请求文件时,您生成一个随机唯一字符串,以此方式为其提供链接:dl.php?k=hd8DcjCjdCkk123然后将此字符串放入数据库,存储其IP地址,可能是会话和时间你已经生成了这个链接。然后另一个用户请求该文件,确保所有的东西(哈希,ip等)匹配并且链接没有过期(例如,自生成以来已经过了N小时)并且如果一切正常,请使用PHP来管道文件。设置一个cron作业以查看数据库并删除过期的条目。你觉得怎么样?

<击> tmpfile

<击>
<击>   

创建一个唯一的临时文件   以读写(w +)模式命名   返回文件句柄。该文件是   关闭时自动删除   (使用fclose()),或者当脚本   结束。

答案 4 :(得分:2)

好的,到目前为止我们有以下要求

  1. 让用户仅在他/她的会话中下载
  2. 没有副本&amp;将链接粘贴给其他人
  3. 用户必须从网站下载,例如没有热门链接
  4. 控制速度
  5. 我们来看看。这是无法正常运行的代码,但它应该按以下方式工作:

    <?php // download.php
    
    session_start(); // start or resume a session
    
    // always sanitize user input
    $fileId  = filter_input(INPUT_GET, 'fileId', FILTER_SANITIZE_NUMBER_INT);
    $token   = filter_input(INPUT_GET, 'token', FILTER_UNSAFE_RAW);
    $referer = filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL);
    $script  = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL);
    
    // mush session_id and fileId into an access token
    $secret        = 'i can haz salt?';
    $expectedToken = md5($secret . session_id() . $fileId);
    
    // check if request came from download.php and has the valid access token
    if(($expectedToken === $token) && ($referer === $script)) {
       $file = realpath('path/to/files/' . $fileId . '.zip');
       if(is_readable($file)) {
            session_destroy(); // optional
            header(/* stuff */);
            fpassthru($file);
            exit;
        }
    }
    // if no file was sent, send the page with the download link.
    ?>
    <html ...
    
    <?php printf('a href="/download.php?fileId=%s&amp;token=%s', 
                  $fileId, $expectedToken); ?>
    
    ...
    </html>
    

    就是这样。无需数据库。这应该涵盖要求1-3。您无法使用PHP控制速度,但如果您在发送文件后没有销毁会话,则可以编写会话计数器并限制用户在会话期间发送的文件数。

    我完全同意这可以比使用这种猴子形式更优雅地解决,但作为概念验证,它应该足够了。

答案 5 :(得分:0)

也许是为了回答迟到但我尝试分享功能googlize!

  

如果您使用CPanel,则可以通过简短快捷的方式阻止外部访问   请求托管文件的名称为: HotLink

您可以在Cpanel上启用HotLinks,并确保没有人可以从其他主机请求您的文件或使用您的文件作为下载参考。

答案 6 :(得分:0)

为了实现这一点,我会创建一个文件并使用chmod保护它 - 使公众无法使用它。或者,或者,将内容保存在数据库表行中,并在需要时获取它。

将其作为文件下载。为此,我将从受保护的文件中获取内容,或者如果它存储在数据库表中,则获取它并简单地输出它。使用php标题,我会给它一个所需的名称,扩展名,指定它的类型,最后强制浏览器将输出下载为实体文件。

这样,您只需要将数据保存在受保护文件或数据库中的一个位置。强制客户端浏览器在条件满足时多次下载,例如,只要用户登录等等。无需担心磁盘空间,制作任何临时文件,cronJobs和/或自动删除文件。