【问题标题】:Php file download corrupting audio filesphp文件下载损坏音频文件
【发布时间】:2018-08-31 09:43:54
【问题描述】:

我一直在用 php 编写一个文件下载器来从我的网站下载一些音频文件(.mid、.wav、.mp3)。下载似乎工作正常,但是当我尝试播放下载的文件时,windows media player 说:

Windows Media Player 无法播放该文件。播放器可能不支持文件类型或可能不支持用于压缩文件的编解码器。

我用文本编辑软件查看了文件,发现“损坏”的文件在文件开头都有一个额外的换行符和“”:

普通文件

RIFF† WAVEfmt D¬ ± 数据@ SÿSÿkÿkÿu o ÷½ [+eŸ0a/ô>T=êFE]JjHLJ¶P—NÊU…S‡[Y _b\'^×[èZ"XïS3Q

损坏的文件:

RIFF† WAVEfmt D¬ ± 数据@ SÿSÿkÿkÿu o÷½ [+eŸ0a/ô>T=êFE]JjHLJ¶P—NÊU…S‡[Y _b\'^×[èZ"XïS3Q

当我删除换行符和“”标签时,音频文件再次工作。 这是我的文件下载脚本:

$eyr = html_entity_decode($_GET['fileUrOpening']);

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary"); 
header("Content-disposition: attachment; filename=".$eyr); 
header('Pragma: public');
readfile($eyr);

它被另一个脚本调用:

 $result = queryMysql("SELECT * FROM fichierschants WHERE chant = '$id';");
  $files = $result->num_rows;

  if ($files == 0) {
    echo '<td> There are no files for this song</td>';
  }else{

    echo '<td>';
    for ($i = 0 ; $i < $files ; ++$i){
        $result->data_seek($i); 
        $eode = $result->fetch_assoc()['emplacement'];
        echo'<a href="./readingFile.php?fileUrOpening=';
        echo $eode;
        echo '"">';
        $result->data_seek($i); 
        echo $result->fetch_assoc()['emplacement']."</a> <br>";
    }
    echo'</td>';
}

我尝试了许多不同的建议方法来下载我的文件,但它们似乎都不能正常工作。
任何帮助将不胜感激,
亚历克斯。

【问题讨论】:

  • 这是您下载脚本中的所有代码还是包含更多代码?另外,您是否检查过原始文件不包含该内容?
  • 这就是这个脚本的全部内容,它只是从其他脚本中调用并获取要下载的文件名
  • 原始文件正常工作,不包含该文件
  • “它只是被其他脚本调用” - 所以这个脚本不是直接从浏览器调用的,在这之前还有更多的代码被执行?请向我们展示从请求开始到您发布的下载脚本的所有代码。您可能还应该使用urldecode() 而不是html_entity_decode()。您还应该对$eyr-变量进行一些验证,以确保人们不会传递其他文件(现在,人们可以请求您服务器上 PHP 具有读取权限的任何文件,以便下载)。
  • 我没有看到您在新代码中“调用”该脚本。虽然有一个链接,但 HTML 看起来有点错误。这个echo '""&gt;'; 应该只是echo '"&gt;';(少一个双引号)。从您显示的代码中,没有任何内容可以将 &lt;/datalist&gt; 添加到文件的开头。一定有什么事情你没有向我们展示。

标签: php audio download


【解决方案1】:

application/octet-stream 在 RFC 2046 中被定义为“任意二进制数据”。也许尝试为音频文件使用正确的标头?您可以获取文件 mime 信息以确定您是否应该使用 Content-Type: audio/mpeg,或 .wav.mid 的等效项。

另外,如果脚本是从其他地方调用的,请确保没有输出回显。我猜没有,否则您将无法正确发送标头,但值得检查您的error_log。 Datalist 是一个 HTML 标记,因此在我看来,该标记来自脚本中的较早部分,可能是缓冲输出或其他内容。无论如何,希望这会有所帮助。

【讨论】:

  • 如果你想强制下载,使用application/octet-stream 是相当标准的。设置正确的内容类型通常会在浏览器中打开文件,这不是您在下载页面上想要的。
  • 不能说我已经看到了,内容处置应该解决这个问题
  • 不适用于所有浏览器。这是“将一堆额外的标题放入其中,因为某些浏览器以他们自己的方式做事”之一。他们今天可能会做得更好,我不知道。无论如何,使用application/octet-stream 不会有什么坏处,因为下载只是将二进制数据发送到客户端。
【解决方案2】:

我终于发现清理输出缓冲区了:

while (ob_get_level()) { ob_end_clean(); }

就在调用 readfile() 之前,避免了文件的损坏!

感谢您的所有建议,我也将它们添加到我的脚本中。

祝你有美好的一天,

亚历克斯

【讨论】:

  • 那么在您向我们展示的代码之前,您确实有更多代码,因为代码中根本没有提到任何输出黄油?
  • 在我尝试了那个代码并且它工作之前,我没有触及任何输出缓冲
猜你喜欢
  • 2015-07-16
  • 2021-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 1970-01-01
  • 2012-02-23
相关资源
最近更新 更多