我的PHP文件下载脚本无法正确下载MP3或MP4文件

时间:2018-09-14 04:05:29

标签: php

我用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脚本(download.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);
}
?>

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

  

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

1 个答案:

答案 0 :(得分:0)

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

  

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

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

  

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

关闭输出缓冲

我怀疑这是问题所在。

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


对此特定问题有一些额外的改进...

  1. 使用exit

    防止文件后出现任何空白
    readfile($file_path);
    exit;
    
  2. 使用URL编码整个文件的基本名称,而不是仅用%20代替空格

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