繁体   English   中英

PHP:如果我强制下载图像已损坏

[英]PHP: image corrupted if I force the download

使用简单的PHP代码时,我的行为很奇怪。 当我尝试使用正确的内容类型强制下载或打印出图像时,输出文件已损坏。

似乎网络服务器(Apache)在文件的开头添加了两个字节( 0x20和0x0A )。

这是代码:

$file = "image.png";
$image = file_get_contents($file);

// Test
file_put_contents("test.png", $image);

// Download
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));

echo $image;

我在同一台服务器上托管的其他网站上使用了相同的代码,没有出现问题。

该问题仅在下载时才存在,因为test.png可以正常工作。 text.png的MD5校验和与原始图像相等。

这是test.png的十六进制代码。

在此处输入图片说明

这是下载后损坏文件的十六进制代码:

在此处输入图片说明

如您所见,开头有2个额外的字节。 如果删除它们,文件将恢复正常工作。

我附上了Wireshark的屏幕(如您所见,这不是浏览器问题):

在此处输入图片说明

我该如何解决?

服务器是带有PHP-5.6的Ubuntu 16.04(是的,由于roundcube的兼容性问题,我将其从7.0降级到5.6)

更新1:我试图查找文件中某处是否有空格+换行符

更新2:

首先:谢谢。

该代码是Wordpress插件的一部分,可使用AJAX系统调用下载。 我写了一个简单的插件测试:

<?php
/*
Plugin Name: Test
Plugin URI: http://www.google.com
Description: Test
Author: Anon
Version: 4.0
*/
function downlod_test() {
echo "test";
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=prova.html');
die();   
}
function iopman_shared_download_doc_ajax() {
downlod_test();
}
add_action('wp_ajax_frontend_download_doc', 'iopman_shared_download_doc_ajax');

//downlod_test();
?>

如果我使用/wp-admin/admin-ajax.php?action=frontend_download_doc调用downlod_test,则会添加2个额外的字节。 如果我直接调用它(通过删除注释),它将起作用。

因此,现在的问题是:如何去除wordpress添加的这些字节?

为了帮助您找到不需要的空格,您可以使用get_included_files()跟踪加载的文件。 此外, 回溯还可能使您的脚本无法正常工作。

在许多情况下,它将来自关闭文件末尾的PHP标记。 由于它们是可选的,因此建议不要使用它们。

找到该空白位置的文件后,只需加载您喜欢的文本编辑器并将其删除(您可能需要启用编辑器的“ 显示隐藏的字符”功能)。

PS我知道这可能是简化的代码来说明问题,但您可能想尝试一下readfile()

$file = "image.png";
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
header("Content-Encoding: gzip");
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header("Content-Length: " . filesize($file));
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
ob_get_clean();
readfile($file);
exit;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM