【问题标题】:My file download script in PHP does not download MP3 or MP4 files properly我的 PHP 文件下载脚本无法正确下载 MP3 或 MP4 文件
【发布时间】:2018-09-14 04:05:29
【问题描述】:

我用 PHP 编写了一个文件下载脚本,它使用户能够从我的服务器下载任何指定的文件。该脚本适用于 .txt、.pdf 和 .jpg 等文件。

但当用户尝试下载任何 .mp3 或 .mp4 文件时,虽然脚本会下载文件,但文件无法使用。与我的原始文件相比,该文件的大小要小得多。该文件无法在任何媒体播放器中打开 - 它已损坏。

我不知道我的这个下载脚本有什么问题。完整代码如下:

界面页面(index.php):

<a href="download.php?file=tutorial.pdf">Download Tutorial (pdf)</a><br /><br />
<a href="download.php?file=music.mp3">Download Music (mp3)</a><br /><br />
<a href="download.php?file=video.mp4">Download Video (mp4)</a>

PHP 脚本(下载.php):

<?php
if(isset($_GET['file']) && !empty($_GET['file']))
{
    $file = $_GET['file'];
    $file_without_spaces = str_replace(' ', "%20", $file);
    $path_parts = pathinfo($file);
    $file_name = $path_parts['basename'];
    $file_path = "files/" . $file_name;
    $file_extension = $path_parts['extension'];

    if(!is_readable($file_path))
    {
        die("File not found!");
    }

    // Figure out the correct MIME type
    $mime_types = array(
                        // Documents
                        "pdf" => "application/pdf",
                        "doc" => "application/msword",
                        "xls" => "application/vnd.ms-excel",
                        "ppt" => "application/vnd.ms-powerpoint",
                        "csv" => "application/csv",
                        "txt" => "text/plain",

                        // Archives
                        "zip" => "application/zip",

                        // Executables
                        "exe" => "application/octet-stream",

                        // Images
                        "jpg" => "image/jpeg",
                        "jpeg" => "image/jpeg",
                        "png" => "image/png",
                        "gif" => "image/gif",
                        "bmp" =>  "image/bmp",

                        // Audio
                        "mp3" => "audio/mpeg",
                        "wav" => "audio/x-wav",

                        // Video
                        "mpeg" => "video/mpeg",
                        "mpg" => "video/mpeg",
                        "mov" => "video/quicktime",
                        "avi" => "video/x-msvideo",
                        "mp4" => "video/mp4",
                        "3gp" => "video/3gpp"
                    );

    if(array_key_exists($file_extension, $mime_types))
    {
        $mime_type = $mime_types[$file_extension];
    }

    header("Content-type: " . $mime_type);
    header("Content-Disposition: attachment; filename=\"$file_without_spaces\"");
    readfile($file_path);
}
?>

我下载了一个大小约为 250 MB 的 .mp4 大文件。结果只有 2 KB。我在记事本中发现了这个错误:

致命错误:允许的内存大小...

【问题讨论】:

  • 试着用文本编辑器打开它
  • 对 mp4 和 mp3 文件使用特定的标题内容类型...如下所示 header("Content-Type: video/mp4"); header("内容长度:".filesize("path/to/mp4")); readfile("路径/到/mp4"); header("内容类型:音频/mp3"); header("内容长度:".filesize("path/to/mp3")); readfile("path/to/mp3");
  • 你设置内容长度了吗????
  • 各位,我解决了!
  • @user5307298 你能在下面的答案栏中写下你如何解决它吗?没有什么比寻找问题的解决方案更糟糕的了

标签: php


【解决方案1】:

readfile() 是一种输出小文件的简单方法。但是对于巨大的媒体文件,它会导致内存耗尽问题和输出缓冲。欲了解更多信息,请访问Why does readfile() exhaust PHP memory?。因此,要处理大文件大小,最好以块的形式输出文件。我在现有代码中添加了以下代码来下载大文件:

set_time_limit(0);
$file_handle = @fopen($file_path, "rb");
while(!feof($file_handle))
{
    print(@fread($file_handle, 1024 * 8));
    ob_flush();
    flush();
}
fclose($file_handle);

现在我们在这个 sn-p 中不再需要 readfile()

【讨论】:

  • 感谢您添加解决方案,但禁用输出缓冲不是更简单吗?
  • 我也在做同样的事情。我无法通过编辑 php.ini 文件来关闭输出缓冲。
【解决方案2】:

在 OP 添加他们自己的答案之前,我会对此有所了解...

致命错误:允许的内存大小...

PHP manual page for readfile() 中有一个非常具体的注释。它说...

readfile() 本身不会出现任何内存问题,即使在发送大文件时也是如此。如果遇到内存不足错误,请确保使用 ob_get_level() 关闭输出缓冲

我怀疑这是问题所在。

要禁用输出缓冲,请确保 output_buffering runtime configuration 设置为 0


针对这个特定问题的一些额外改进是......

  1. 使用exit防止文件后出现任何意外空格

    readfile($file_path);
    exit;
    
  2. 不是只用%20替换空格,而是对整个文件基名进行URL编码

    header(sprintf('Content-Disposition: attachment; filename="%s"',
            urlencode($file_name));
    

【讨论】:

    猜你喜欢
    • 2014-02-18
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    相关资源
    最近更新 更多