我正在尝试使用CGI脚本接受并保存使用HTTP POST发送zip文件的程序中的文件。
在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文件,但我对此表示怀疑。我有什么办法可以进一步排除故障吗?
答案 0 :(得分:5)
你正在逐行读取.zip文件,这是一个很大的错误。毕竟,行仅与文本文件相关。
一次性阅读整个内容,或者如果必须,请以合理大小的块进行。在这个例子中,它是以1024字节的块读取的,但是你可以轻松地使用更大的值,例如16MB(1 <24)或任何看似合适的值:
my $data;
while (read($upload_file, $data, 1024))
{
print TMP, $data;
}
答案 1 :(得分: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;
答案 2 :(得分:0)
标题中的“\ r \ n”可能是一个线索。输出文件是否包含“\ r \ n”序列?你能/你应该在binmode
文件句柄上做$upload_file
吗?