2016-06-07 34 views
0

我有一個簡單的PHP代碼奇怪的行爲。當我嘗試使用正確的內容類型強制下載或打印圖像時,輸出文件已損壞。PHP:圖片損壞,如果我強制下載

似乎webserver(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的十六進制代碼。

enter image description here

這是損壞的文件的十六進制代碼下載後:

enter image description here

正如你所看到的,有在開始2個額外的字節。如果我刪除它們,文件將恢復正常工作。

我附上的Wireshark的屏幕(你可以看看是不是瀏覽器的問題):

enter image description here

我怎樣才能解決呢?

該服務器的Ubuntu 16.04與PHP-5.6(是的,我做了從7.0降級到5.6與roundcube兼容性問題)

更新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(); 
?> 

如果我打電話downlod_test與/wp-admin/admin-ajax.php?action=frontend_download_doc它增加了2個額外的字節。如果我直接調用它(通過刪除評論),它就可以工作。

所以現在的問題是:如何去掉wordpress添加的這些字節?

+3

x20是一個空格,而x0A是一個換行符(又名'\ n')。也許這可以幫助你找出它來自哪裏。你顯示的代碼不應該產生它們。 –

+0

如何去除它們?使用get_included_files(),debug_print_backtrace()查找它們,然後在編輯器中加載該文件並將其刪除。 –

回答

1

爲了幫助您找到不需要的空白,您可以使用get_included_files()跟蹤加載的文件。此外,backtrace也可能會讓你的腳本所做的工作變得輕鬆一些。

在很多情況下,它會來自在文件末尾關閉PHP標籤。由於它們是可選的,因此建議不要使用它們。

一旦找到文件所在的空白處,你只需要加載你最喜歡的文本編輯器並刪除它們(你可能需要啓用編輯器的顯示隱藏的字符功能)。

P.S.我明白這可能是簡化的代碼來說明問題,但您可能想嘗試一下readfile()

0
$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; 
+0

Ali Khanusiya,你的標題代碼是做什麼的?有什麼問題,它是如何解決它的? – alexis

+1

@alexis這個答案基本上建議使用'ob_get_clean();'來忽略虛假空格,但他顯然[缺少一點](https://3v4l.org/Ba5fJ)。如果您之前沒有啓動輸出緩衝區,則不能清空輸出緩衝區,這樣做比修復問題複雜得多。 –