We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

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

dsweeney
dsweeney asked
on
Medium Priority
208 Views
Last Modified: 2010-03-04
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.
Comment
Watch Question

ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
as in binmode(STDIN)?

Author

Commented:
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

}

Commented:
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...

Commented:
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.

Author

Commented:
I am using IIS 3.0, Netscape 4.01.

Author

Commented:
also same result with IE 4.0.  Sombody has to have the same problem!!

Author

Commented:
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
ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
So what were the extra bytes tacked on, and where in the file were they?

Commented:
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



Author

Commented:
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?

Commented:
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.

Author

Commented:
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.

Commented:
>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.  

Author

Commented:
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"????
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.