使用 php readfile 确定下载成功

2022-01-02 00:00:00 download readfile php

我需要知道用户是否选择了下载然后点击了取消按钮,这与有错误的 readfile 不同.我检查了 readfile 函数返回的计数,但即使用户从另存为"对话框取消下载,它也会显示文件中的字节数.

I need to know if a user selected download then clicked the cancel button, which is not the same as readfile having an error. I have inspected the count returned by the readfile function, but it shows the bytes in the file even if the user canceled the download from the Save As dialog.

需要这样做的原因是因为我的网站有一次性下载,其中成员允许另一次使用以下载他们的文件一次,然后该权限消失.但是,如果会员点击下载按钮然后决定不立即下载,我不希望我的数据库更新以显示他们获得了文件.

The reason this is needed is because my site has a one-time download, where a member gives permission for another use to download their file one time, then the permission goes away. But if a member clicks the download button then decides not to download it right then, I dont' want my database to get updated to show they got the file.

这涉及知识产权保护,因为文件是上传它们的成员的财产,我需要保留其他成员下载文件的确切内容的审计跟踪,以防他们开始在互联网上传播.但是如果 readfile 函数总是反映文件大小(意味着这些字节是以某种方式传输的),我就无法知道文件是否真的被下载了.

This deals with intellectual property protection since the files are the property of the member who uploaded them, and I need to keep an audit trail of exactly what other members downloaded the file in case they start floating around the internet. But if the readfile function always reflects the filesize (meaning those bytes were transferred in some way), I have no way to know if the file was actually downloaded.

我看过很多关于这个主题的帖子,但没有真正解决经常需要的问题 - 他们是否下载了它?仅仅知道他们点击了下载按钮并不能真正说明他们是否决定继续下载,因为另存为"对话框允许某人取消实际完成下载.

I have seen a number of posts about this subject, but no real solutions to what has to be a frequent need - did they download it or not? Just knowing that they clicked the download button doesn't really say whether they decided to go through with it since the Save As dialog box allows someone to cancel the actual completion of the download.

为了完整起见,这是我的下载代码,直到 readfile 函数:

For completeness, here is my download code up until the readfile function:

    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header("Content-Disposition: attachment; filename=$download_name");
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize("sub/$doc_file"));
    ob_clean();
    flush();
    $wasdownloaded = readfile("sub/$doc_file");

推荐答案

您首先需要 ignore_user_abort().

这将允许您的脚本在用户点击取消或退出后继续运行.

This would allow your script to continue on after the user has hit cancel, or escape.

然后您必须打印文件并不断检查connection_aborted().

You would then have to print out the file and continuously check with connection_aborted().

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=$download_name");
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize("sub/$doc_file"));
ob_clean();
flush();

$fp=fopen("sub/$doc_file","rb");

while(!feof($fp))
{
    print(fread($fp,1024*8));

    flush();
    ob_flush();
    if( connection_aborted() )
    {
        //do code for handling aborts
    }
}

相关文章