php、文件下载

发布于 2024-10-31 08:14:46 字数 797 浏览 1 评论 0原文

我正在使用简单的文件下载脚本:

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    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($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

它在我的本地服务器上运行,最大容量为 200mb。

当我在网站中尝试此代码时,它会下载 173KB 而不是 200MB 的文件。

我检查了所有内容,编写了一些自定义代码(使用 ob 函数和 fread 而不是 readfile),但无法下载大文件。

谢谢您的回答。

  • 我正在使用 Apache 2.2、PHP 5.3
  • 处理大文件的所有 PHP 设置都可以。 (执行时间、内存限制、...

I am using the simple file downloading script:

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    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($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}

It is working on my localserver upto 200mb.

When i try this code in my website it downloads 173KB instead of 200MB file.

I checked everything, wrote some custom code (using ob functions and fread instead of readfile) but can't download big files.

Thank you for your answers.

  • I am using Apache 2.2, PHP 5.3
  • All PHP settings to deal with big files are ok. (execution times, memory limits, ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梨涡少年 2024-11-07 08:14:46

我对以下代码遇到的一个问题是您无法控制输出流,您让 PHP 处理它而不确切知道后台发生了什么:

您应该做的是设置一个可以控制和复制的输出系统accros服务器。

例如:

if (file_exists($file))
{
    if (FALSE!== ($handler = fopen($file, 'r')))
    {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: chunked'); //changed to chunked
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        //header('Content-Length: ' . filesize($file)); //Remove

        //Send the content in chunks
        while(false !== ($chunk = fread($handler,4096)))
        {
            echo $chunk;
        }
    }
    exit;
}
echo "<h1>Content error</h1><p>The file does not exist!</p>";

这只是基本的,但请尝试一下!

另请阅读我的回复: file_get_contents => PHP 致命错误:允许的内存耗尽

One issue I have with the following code is you have no control over the output stream, your letting PHP handle it without knowing exactly what is going on within the background:

What you should do is set up an output system that you can control and replicated accros servers.

For example:

if (file_exists($file))
{
    if (FALSE!== ($handler = fopen($file, 'r')))
    {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: chunked'); //changed to chunked
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        //header('Content-Length: ' . filesize($file)); //Remove

        //Send the content in chunks
        while(false !== ($chunk = fread($handler,4096)))
        {
            echo $chunk;
        }
    }
    exit;
}
echo "<h1>Content error</h1><p>The file does not exist!</p>";

This is only basic but give it a go!

Also read my reply here: file_get_contents => PHP Fatal error: Allowed memory exhausted

终弃我 2024-11-07 08:14:46

看起来 readfile 可能会遇到长文件的问题。正如@Khez 所问,可能是脚本运行时间太长。快速谷歌搜索得到了几个对文件进行分块的示例。

http://teddy.fr/blog/how-serve-big-文件通过 php
http://www.php.net/manual/en/function。 readfile.php#99406

It seems readfile can have issues with long files. As @Khez asked, it could be that the script is running for too long. A quick Googling resulted in a couple examples of chunking the file.

http://teddy.fr/blog/how-serve-big-files-through-php
http://www.php.net/manual/en/function.readfile.php#99406

千紇 2024-11-07 08:14:46

针对某些场景的一种解决方案是,您可以使用 PHP 脚本智能地决定从何处下载什么文件,但您可以将重定向返回到客户端,然后包含要处理的直接链接,而不是直接从 PHP 发送文件仅由网络服务器。

这至少可以通过两种方式完成:PHP 脚本将文件复制到“下载区域”,例如,可以通过其他后台/服务脚本定期清除“旧”文件,或者将真实的永久位置公开给客户。

当然,每种解决方案都存在缺点。在这种情况下,根据请求文件的客户端(curl、wget、GUI 浏览器),它们可能不支持您所做的重定向,而在另一种情况下,文件非常暴露于外部世界,并且可以随时读取而无需PHP 脚本的(访问)控制。

One solution to certain scenarios is that you can use PHP-script to intelligently decide what file from where to download, but instead of sending the file directly from PHP, you could return a redirection to the client which then contains the direct link which is processed by the web server alone.

This could be done at least in two ways: either PHP-script copies the file into a "download zone" which for example might be cleaned from "old" files regularly by some other background/service script or you expose the real permanent location to the clients.

There are of course drawbacks as is the case with each solution. In this one is that depending on the clients (curl, wget, GUI browser) requesting the file they may not support redirection you make and in the other one, the files are very exposed to the outer world and can be at all times read without the (access) control of the PHP script.

做个少女永远怀春 2024-11-07 08:14:46

您是否确保您的脚本可以运行足够长的时间并且有足够的时间记忆?

你真的需要输出缓冲吗?

Have you made sure your script can run long enough and has enough memory?

Do you really need output buffering ?

酒儿 2024-11-07 08:14:46

真正的解决方案是避免使用 PHP 脚本将文件发送到客户端,这有点过分了,您的网络服务器更适合这项任务。

想必您有通过 PHP 发送文件的原因,也许用户必须首先进行身份验证?如果是这种情况,那么您应该使用 X-Accel-Redirect (如果您使用的是 nginx)或X-Sendfile(以前的 X-LIGHTTPD-send-file)在 lighttpd 上。

如果您使用 Apache,我发现了一些对 mod_xsendfile 的引用,但我个人从未使用过它,如果您有托管,我怀疑它是否已为您安装。

如果这些解决方案站不住脚,我深表歉意,但我确实需要有关实际问题的更多信息:为什么首先通过 PHP 发送这些文件?

The real solution is to avoid using a PHP script for just sending a file to the client, it's overkill and your webserver is better suited for the task.

Presumably you have a reason for sending the files through PHP, perhaps users must authenticate first? If that is the case then you should use X-Accel-Redirect (if you're using nginx) or X-Sendfile (previously X-LIGHTTPD-send-file) on lighttpd.

If you're using Apache I've found a few references to mod_xsendfile but I've never used it personally, and I doubt it's installed for you if you have managed hosting.

If these solutions are untenable I apologise, but I really need more information on the actual problem: Why are you sending these files through PHP in the first place?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文