强制下载tar压缩包的标头

3

我有一个tar归档文件存储在服务器上,必须通过php可下载。这是我使用的代码:

$content=file_get_contents($tar);
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=$tar");
header("Content-Length: ".strlen($content));    
unlink($name);
die($content);

文件已下载,但是它损坏了,无法打开。我认为头部信息有问题,因为服务器上的文件可以打开而不会出现问题。您知道如何解决这个问题吗?

更新 我尝试像这样打印一个 iframe:

<iframe src="<?php echo $tar?>"></iframe>

下载可以正常进行,因此我确定头部信息中缺少某些内容。


使用filesize函数会更好,不是吗? - Matt Ellen
同样的事情,但我必须使用 die - mck89
1
你是否可能超过了max_execution_time、post_max_size或upload_max_filesize的限制? - bcosca
我看不到任何错误。 - mck89
2
请在标准文本编辑器中检查已下载的文件,并查看文件内容中是否有任何 PHP 错误消息(例如,头部已发送)。 - Mark Baker
5个回答

7

在我必须这样做的时候,我使用了以下代码:

function _Download($f_location, $f_name){
 header('Content-Description: File Transfer');
 header('Content-Type: application/octet-stream');
 header('Content-Length: ' . filesize($f_location));
 header('Content-Disposition: attachment; filename=' . basename($f_name));
 readfile($f_location);
 }

_Download("../directory/to/tar/raj.tar", "raj.tar");
//or
_Download("/var/www/vhost/domain.com/httpdocs/directory/to/tar/raj.tar", "raj.tar");

试一试。


我已经尝试了那个,但结果一样。我认为编码标头有些缺失。 - mck89
其他文件下载正常吗?例如图片。我现在正在为您进行本地测试。 - PHPology
好的,看起来无论我用什么文件都可以正常工作 :-|你是怎么调用这个文件的?像http://localhost/download.php这样直接调用吗? - PHPology
2
我曾经遇到过类似的问题。原来是PHP在文件之前发送了一些额外的数据。在调用readfile之前,我添加了'ob_clean()'函数的调用 - 现在它可以正常工作了。 - nimrodm

5
不要使用file_get_contents(),然后使用echoprint输出文件。这会将整个文件的内容加载到内存中。一个大文件可能会超出脚本的memory_limit并终止脚本。
如果要将文件内容转储到客户端,最好使用readfile() - 它会正确地读取文件块并将它们传输到客户端,而不会超出可用内存。只需记得在执行此操作之前关闭输出缓冲区,否则您实际上又在执行file_get_contents()
因此,您可以得到以下结果:
$tar = 'somefile.tar';
$tar_path = '/the/full/path/to/where/the/file/is' . $tar;
$size = filesize($tar_path);

header("Content-Type: application/x-tar");
header("Content-Disposition: attachment; filename='".$tar."'");
header("Content-Length: $size");    
header("Content-Transfer-Encoding: binary");

readfile($tar_path);

如果你的tar文件实际上是gzipped,则使用"application/x-gtar"代替。 如果下载后文件仍然损坏,请在客户端进行一些检查: 1. 下载的文件是否为0字节,但下载过程似乎比传输0字节要花费更长的时间,那么就有一些客户端阻止了下载。病毒扫描器?木马? 2. 下载的文件部分存在,但比原始文件小?某些因素导致传输过早中断。过于急切的防火墙?下载管理器崩溃?服务器上激活输出缓冲区,但最后一个缓冲桶未被正确刷新? 3. 下载的文件与原始文件大小相同吗?在两个副本上执行md5 / sha1 / crc校验和。如果这些相同,则打开文件的应用程序存在问题,而不是文件本身。 4. 下载的文件是否比原始文件大?在记事本中(或者使用notepad ++等更好的软件,它不需要打开大文件需要很长时间),查看是否在文件开头或结尾处插入了任何PHP警告消息或一些看不见的空白字符。

1
尝试类似以下的代码:
$s_filePath = 'somefile.ext';
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'. s_filePath.'"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
header('Cache-control: private');
header('Pragma: private');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header("Content-Length: ".filesize($s_filePath));

$r_fh = fopen($s_filePath,'r');
while(feof($r_fh) === false) {
    $s_part = fread($r_fh,10240);
    echo $s_part;
}
fclose($r_fh);
exit();

相同的结果。我认为编码头有问题。 - mck89

1

使用 Content-Type: application/octet-stream 或 Content-Type: application/x-gtar


0

请务必不要输出非文件输出的任何东西。在头部之前调用 ob_clean()。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接