2009-09-18 51 views
1

我正在嘗試使用CGI腳本接受並保存使用HTTP POST發送zip文件的程序中的文件。爲什麼我的.zip文件在HTTP文件上傳後損壞?

在HTTP標頭的MIME部分,它看起來是這樣的:

Content-Disposition: form-data; name="el_upload_file_0"; filename="BugReport.zip";\r\n 
Content-Type: application/octet-stream\r\n\r\n 

在我的CGI代碼,我使用的是這樣的:

use CGI; 
use strict; 
my $cgi = CGI->new; 
my $upload_file = $cgi->upload('el_upload_file_0'); 
my $time = time; 

my $filename = "/tmp/$time.zip"; 
open TMP, ">$filename"; 
binmode TMP; 
while (<$upload_file>) { 
    print TMP $_; 
} 
close TMP; 

是不斷得到保存的文件是某種越來越腐敗,並不是一個有效的zip文件。 HTTP請求由C#應用程序發送,可能它發送的是損壞的zip文件,但我對此表示懷疑。我能做些什麼來進一步排除故障?

回答

3

您上傳的文件和最終保存的文件有什麼區別?看看每個十六進制轉儲。

我知道這聽起來很愚蠢,但只是嘗試將您試圖上傳到服務器的文件複製到服務器而不使用CGI腳本。你還可以在那裏解壓縮嗎?同樣,您是否可以從服務器上載文件,將其複製回客戶端計算機,然後將其解壓縮?

HTTP標頭的其餘部分是什麼樣的?你正在改變字符集或任何東西?

我不懷疑文件翻譯有問題,因爲CGI應該已經爲您設置了。所以,一旦有人說「應該」,你必須仔細檢查:)。 CGI.pm中有一行可以自動檢測需要binmode的系統,所以我認爲你不需要這個$upload_file。然而,也許CGI.pm得到它錯了你:

$needs_binmode = $OS=~/^(WINDOWS|DOS|OS2|MSWin|CYGWIN|NETWARE)/; 

你可以嘗試變量設置爲true,自己只是爲了確保:

use CGI; 
$CGI::needs_binmode = 1; 
5

你是在一個.zip文件讀取行按行,這是一個很大的錯誤。畢竟,行只與文本文件相關。

一次讀完所有東西,或者如果必須的話,在合理大小的區塊中完成。在這個例子中它被讀取1024個字節的塊,但你可以很容易地使用一個較大的值,如16MB(1 < < 24)或任何似乎是恰當的:

my $data; 
while (read($upload_file, $data, 1024)) 
{ 
    print TMP, $data; 
} 
0

的「\ r \ n」的在標題中可能是一個線索。輸出文件是否包含「\ r \ n」序列?你能/你應該在$upload_file文件句柄上做一個binmode嗎?