2009-09-18 52 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吗?