Link to home
Start Free TrialLog in
Avatar of dsweeney
dsweeney

asked on

saving an (web) uploaded file in binary format on NT

I am using netscapes (4.04)  file upload form element with the multipart/form-data encoding type to send a file from the client to a directory on the webserver (IIS).  Works great for text files, but binary files (exe, jpg, gif, etc) get 100-200 bytes tacked onto them, cause a network error message to pop up on the client.  Copy actually happens, but file is a wee bit bigger and no longer valid.  I have seen the binmode() function used when the server is sending a binary to the client (like with the FLY graphic program), but I dont know if there is an equivalent for the servers STDIN and the output file on the server.
Avatar of ozo
ozo
Flag of United States of America image

as in binmode(STDIN)?
Avatar of dsweeney
dsweeney

ASKER

yes, but I suck at all that (better at chopping out sections of code that work and then figuring it our once i've seen it work once).  I gave it a stab on my own binmode(STDIN)
and binmode(OUTFILE) but there is a chunk size parametaer or something that I couldnt get to work.  A working example code would be great, thats why I put up so many points...  Here is my current code, which works great for uploading text files but doesnt work for binary files.  Also tried it first without the binmode statements, that didnt work either.

#!/usr/local/bin/perl
#upload.pl

$upload_dir = "d:\\temp\\incoming\\";
$cgiurl = "/cgi-bin";

#------------------------------------------------------
if ($ENV{'REQUEST_METHOD'} eq "POST"){
#---------------read network input
binmode(STDIN);
$len = 0;
$input = '';
while ($len != $ENV{'CONTENT_LENGTH'}) {
      $buf = '';
      $len += sysread(STDIN, $buf, $ENV{'CONTENT_LENGTH'});
      $input .= $buf;
}

if ($ENV{'CONTENT_TYPE'} =~ /multipart\/form-data; boundary=(.+)$/) {
      $boundary = '--' . $1;
      @list = split(/$boundary/, $input);
      $header_body = $list[1];
      $header_body =~ /\r\n\r\n|\n\n/;  #sep header and body
      $header = $`;
      $body = $';
      $body =~ s/\r\n$//;
      $GLOBAL{'FILE_CONTENT'} = $body;
      #---------------parse header
      $header =~ /filename=\"(.+)\"/;
      $GLOBAL{'FILE_NAME'} = $1;
      $GLOBAL{'FILE_NAME'} =~ s/\"//g;

} #----- end if
#-----------------handle upload
$filename = $GLOBAL{'FILE_NAME'};
$filename =~ s/.+\\([^\\]+)$|.+\/([^\/]+)$/\1/;
$filename =~ tr/A-Z/a-z/;
$write_file = $upload_dir . $filename;

open (OUTFILE, ">$write_file");
binmode(OUTFILE);
print OUTFILE $GLOBAL{'FILE_CONTENT'};
close (OUTFILE);

# --------------Send upload complete message
print "Content-type: text/html\n\n";
print <<"endofhtml";
<html>
<head>
<title>Upload Complete</title>
</head>
<body>
<br>
<center>
<br><br>
<font size="3">
<b>Your file <font color=blue>"$filename"<font color=black><br>
has been uploaded.</b>
</body>
</html>
endofhtml

exit;

} else {
#if this page was not the result of a post, just show the form only
#-------------------------------------------------------------------------
print "Content-type: text/html\n\n";
print <<"endofhtml";

<HTML>
<HEAD>
<TITLE>File Upload</TITLE>
</HEAD>

<BODY>
<center>
<FORM NAME="upload" ACTION="$cgiurl/upload.pl" METHOD=POST enctype="multipart/form-data">
<INPUT TYPE="file" NAME="filename">
<INPUT TYPE="SUBMIT" VALUE="Send File">
</form>

</CENTER>
</BODY>
</HTML>

endofhtml

}
Your script worked perfectly for me (IIS 1.0, NS 4.03)... perhaps there's something about your environment. Bug in your perl version? Unlikely, but...
Wonder if your particular server isn't trying to parse response headers into the file being uploaded? 100 - 200 bytes would be about the size of these.
I am using IIS 3.0, Netscape 4.01.
also same result with IE 4.0.  Sombody has to have the same problem!!
Also I did a view of the binary file in a text editor and there was no "text data" of any sort
so I dont think it is the response header being tacked on
So what were the extra bytes tacked on, and where in the file were they?
I set up your upload script. Access it on my server with the below URL and upload the file you been testing. Then, take the file that has been corrupeted and upload it as "bad.exe" and I'll open it and compare it line by line with the good copy.

http://206.165.19.129/cgi-bin/upload.pl



Ozo:  I am not that good of a programmer that I understand the binary files and how to compare or what im looking for

Biffo:  wont both versions I upload end up with the extra data since i am using the same script?
dsweeney, I (and everyone else) who has tried your script has reported it works as-is. Therefore it *has* to be something with your system. The most likely culprit is a perl which doesn't implement binmode properly - essentially the questions about the differences and the request to upload the files for someone else to check are attempts to verify this.

You missed my question about which perl version you are using... so what is it? If it's an old version (off the resource kit cdrom, for example) you should get and install the latest from http://www.activestate.com/pw32/ I don't remember hearing of such a bug, but something is strange with your system and a reinstall of perl might help.
alamo:  I am using build 313 (pw32i313) I think, of Activestates 5.003, as well as the IIS DLL (thats whats is associated), same build.  I will try downloading the latest build tonight and reinstall.
>Biffo:  wont both versions I upload end up with the extra data since i am
 > using the same script?

No, the script is on my end and not yours. Just upload the bad file that got corrupted and the clean version of it. I want to see the good and the bad copy. I have a binary file comparison program.  
alamo:  Upgrading to 316 from 313 solved the problem.  I am very grateful.  I would like to split the points 60-40 between alamo/biffo (alamo solved, biffo made a great effort) but I dont even know how to award the points.  There is no placew to click to say "this person solved my problem"....  can I split the points?  Where do I say "xxxx solved it"????
ASKER CERTIFIED SOLUTION
Avatar of alamo
alamo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial