Important alert: (current site time 7/15/2013 8:38:20 PM EDT)
 

VB icon

CGI Perl - File Upload

Email
Submitted on: 12/21/2001 2:46:02 PM
By: Dax Ahweng  
Level: Beginner
User Rating: By 18 Users
Compatibility: 5.0 (all versions)
Views: 75346
author picture
(About the author)
 
     Shows you the key of how to upload a binary file using perl/cgi. (what nobody tells you (i had to figure it out on my own!)) PS if this code helps, i'd appreciate a vote
 
code:
Can't Copy and Paste this?
Click here for a copy-and-paste friendly version of this code!
 
Terms of Agreement:   
By using this code, you agree to the following terms...   
  1. You may use this code in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this code (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this code from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the code or code's description.
				
=**************************************
= Name: CGI Perl - File Upload
= Description:Shows you the key of how to upload a binary file using perl/cgi. (what nobody tells you (i had to figure it out on my own!))
PS if this code helps, i'd appreciate a vote
= By: Dax Ahweng
=
= Inputs:You will need to make a form with the following properties:
<form enctype="multipart/form-data" method=post action="~script_file_location~">
<input type=file name=filex>
and of course, a submit button
=
= Returns:Me script returns a confirmation of the upload and size of the uploaded file.
=
= Assumes:You need to have a basic knowledge of Perl, including variables, arrays, splice(), binmode() and handles.. but not too important.
All you need is logic.
=
= Side Effects:Not optimised for text file upload, assumes you are uploading a JPEG, allows only 1 file upload (but can be easily optimised for more)
=
=This code is copyrighted and has= limited warranties.Please see http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=262&lngWId=6=for details.=**************************************

#!/usr/bin/perl
###	NOTE: this is to demonstrate binary file upload, text file uploading is simple, but if you want to know how to do textfile uploading, just remove all the binmode() functions and that's it!
use CGI;
###	Set Maximum Upload size to 2MB (prevent ppl from uploading extremely large files or other such malicious stuff)
$CGI::POST_MAX = 2048;
print "content-type: text/html\n\n";
###	Set Standard Input to Binary Mode (this is critical for binary data (e.g. images) - the key piece of this code which nobody tells you (except me))
binmode(STDIN);
@inx = <STDIN>;
###	This is just for a single file upload.. you can improve the code to include boundary separations and stuff like that..
###	These two lines delete the boundary and file info which comes with the formfeed and leaves only the binary data
splice(@inx,0,4);
splice(@inx,$#inx,1);
$in = join("",@inx);
$in = substr($in,0,length($in) - 2);;
###	This next sniplet assumes you are uploading a JPEG file and saves it as z.jpg in the folder this script is stored
###	You can also further improve the script by retreiving the filename from the 'spliced' lines
open(ff,">z.jpg");
###	Set file output to binary mode (since you're assuming to write a binary file)
binmode(ff);
print ff $in;
close(ff);
print "DONE, Uploaded Size: ".length($in)." bytes";


Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this code (in the Beginner category)?
(The code with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)
 

Other User Comments
12/29/2001 11:24:31 PMKalpana

Hi Dave,

Even I am a beginner in Perl, and found your code simple and easy too.

I have written some good guestbooks, form emailers, and discussion forums in perl.

Kalpana
(If this comment was disrespectful, please report it.)

 
12/31/2001 4:51:09 PMDax Ahweng

yea, cool.. all you have to remember is the binmode, otherwise it outputs as a text file :)
(If this comment was disrespectful, please report it.)

 
2/6/2002 7:17:27 PMMatthias Spinner

Hmm, don't know why, but it seems like it doesn't work correctly when I try it.
I can upload a picture without problems, but when I want to look at it, it can't load it (like it wouldn't exist.) but with the ftp programm I can see it, and when I download it with it and start it on my local hard disc, I see it perfectly... what am I doing wrong?


(If this comment was disrespectful, please report it.)

 
2/6/2002 11:37:57 PMDax Ahweng

hmm... well, i cant tell, since you said it works fine when you download it with the ftp program, the script must be fine.. maybe there's a problem with your URL? or something?
(If this comment was disrespectful, please report it.)

 
3/15/2002 1:51:51 PMmeth0s

Nice man I am new to perl and a example like this exlpains everything to me
(If this comment was disrespectful, please report it.)

 
3/20/2002 6:51:41 PMbruno

it's kool...

this example exlpains some things very good
[de unde sugy pula]
(If this comment was disrespectful, please report it.)

 
6/6/2002 5:32:59 AMSuper--s

I wish there were more than just about 30 cgi uploading scripts on the net...
(If this comment was disrespectful, please report it.)

 
6/6/2002 4:16:23 PMDax Ahweng

If you need any help in modifying the above or creating your own upload script, i can give an overview/help if you want...
(If this comment was disrespectful, please report it.)

 
7/23/2002 11:20:21 PMms

Hey your codes are really great man..
but i'm having a small problem here, and wondering whether you can help me with it.
I wrote this code to upload a file using 2 methods. One is using a textfile to type in the file name, then use a submit button. the other one is by entering the file name inside the code itself using a hidden object and a submit button. Somehow the one with the hidden object is not working.
Would you know why it's not working??
Thanks once again man!!
(If this comment was disrespectful, please report it.)

 
7/24/2002 7:40:48 AMDax Ahweng

i'll email you concerning this!
(If this comment was disrespectful, please report it.)

 
7/27/2002 4:22:00 AMAkujin

it's nice to know some people still put value into commenting their code. I'm new to perl, and it's a bit confusing because i work a lot with Object Oriented Programming such as Java and C++. Yours is the only file upload script i've found that is commented so i know what the hell is going on. Thanks
(If this comment was disrespectful, please report it.)

 
7/30/2002 5:46:24 PMwwendorf

I used this code, and it works great, but I need to be able to use the cgi-lib library, and the same techniques you use in the cgi.pm don't work in cgi-lib. I have gotten files to upload in cgi-lib, but only text files work. I can't get binary files to upload without scrambling to the point they won't open. Any idea? Feel free to email me direct if you can.

Thanks,
Wade

(If this comment was disrespectful, please report it.)

 
1/21/2003 7:24:10 PM

I am new to perl. I am trying to use this script to move a graphics file from one of my servers and make it available on the other. I have tried to modify the script to work from a file that I have opened instead of STDIN. I just can't seem to get it to work. Any ideas?
(If this comment was disrespectful, please report it.)

 
4/3/2003 1:21:20 PM

#catch the header stuff
($id,$data,$type) = splice(@inx,0,4);
splice(@inx,$#inx,1);
#split the data
($tmp,$button,$fileName) = split(/;/,$data);
#replace all with the name value
$button=~s/.*name=
(If this comment was disrespectful, please report it.)

 
4/3/2003 1:22:41 PM

try again
($id,$data,$type) = splice(@inx,0,4);
splice(@inx,$#inx,1);
($tmp,$button,$fileName) = split(/;/,$data);
$button=~s/.*name="(.*)".*/$1/;
$fileName=~s/.*filename="(.*)".* /$1/;

(If this comment was disrespectful, please report it.)

 
4/24/2003 12:25:52 AM

how can i save multiple files and not have it overwriting all the time? i am way too new at this to know anything :)
could someone email me the answer?mike.opitz@shaw.ca
(If this comment was disrespectful, please report it.)

 
4/28/2003 4:12:19 AMDax Ahweng

well, i emailed you the answer.. didnt know you had wrote here as well until now.. erm, there is a guy that took my code and made it save to the same filename as the file being uploaded, so that could be useful!

vote for me people :D!
(If this comment was disrespectful, please report it.)

 
5/23/2003 5:25:30 AM

The jpg was uploaded but the picture is no longer readable??!!
(If this comment was disrespectful, please report it.)

 
5/23/2003 11:48:06 AMDax Ahweng

I need more info to know what's wrong.. otherwise, i have no idea why it's not readable...
(If this comment was disrespectful, please report it.)

 
6/27/2003 3:55:59 PM

MAN THIS IS AWESOME! I'VE BEEN LOOKING FOR THIS SCRIPT FOREVER! IF YOU COULD HAVE THIS SENT TO MY EMAIL USEING SENDMAIL THAT WOULD BE EVEN BETTER!
(If this comment was disrespectful, please report it.)

 
6/28/2003 1:05:10 PMDax Ahweng

- filename -

you can extract the filename from the spliced lines at the beginning of @inx
and replace z.jpg with that!

- sendmail -

i know it's possible, i just dont know how it's done, the info for that is readily available though, on the internet...
search for qmail as the sendmail program...
(If this comment was disrespectful, please report it.)

 
7/14/2003 12:08:15 AMChris Stratford

can you please email me a modified version, where you can input a filename to save as?

eg. if you want to upload a file, and you need to pick a filename. i want the form to have:

and


and then
(If this comment was disrespectful, please report it.)

 
7/14/2003 12:08:40 AMChris Stratford

and then

btu yeah

btw - my email is

neester_@hotmail.com
(If this comment was disrespectful, please report it.)

 
7/14/2003 12:11:08 AMChris Stratford

sorry its me again...

use CGI qw(:standard :form);
my $query = new CGI();
my $q_file = $query->param('filex');
my $q_filename = $query->param('filename');


can you use that sort of thing here?
because htat would be soooo easy then (wouldn't it?)
(If this comment was disrespectful, please report it.)

 
7/24/2003 10:12:27 AM

Great Script! I want to add it to my existing form, so how do I modify the script so instead of going through STDIN, it only goes for the filex variable.
Thanks in Advance!
(If this comment was disrespectful, please report it.)

 
7/24/2003 12:24:34 PMDax Ahweng

well, STDIN is the method by which the data is passed to the script... the only other way i can think of is the $ENV{QUERY_STRING} if i remember correctly... and this way is impossible cause you cant pass binary data through the address bar, lol!

if i get some free time, which is quite probable, i will just improve on this code.

the idea was to give you the 'secret' to BINARY file uploads... an average programmer should be able to do the rest...
(If this comment was disrespectful, please report it.)

 
7/24/2003 12:28:31 PMDax Ahweng

oh.. but if you want to separate the data from the rest of the form without splicing it, you can simply process the boundaries (make a test script to analyse the boundaries standard format by print(ing) the whole formfeed... then devise code to filter the data (removing all the boundaries in a more systematic way than splicing them off, since the boundary header contains the data info, including filename!
(If this comment was disrespectful, please report it.)

 
7/24/2003 12:45:16 PMDax Ahweng

ps, i'd appreciate a vote people ;)
(If this comment was disrespectful, please report it.)

 
12/10/2003 2:42:26 PM

How can you load in a text file or a binary file, I assume do a check on STDIN to see what type of data it is, and then set your mode, but by that time, you have already read something from standard in... so how do you handle both a text and a binary file?
(If this comment was disrespectful, please report it.)

 
2/20/2004 2:28:25 AMSachin G

Great Script Man !!!
Can you please tell me how can i use this to upload a file to another machine i.e. i want to run this script on a machime x.x.x.x which uploads a file to machine y.y.y.y.
Thanks in advance ....Cheers
(If this comment was disrespectful, please report it.)

 
2/20/2004 8:30:56 AMDax Ahweng

That's a totally different story, but I guess you could have this script on machine y.y.y.y, then you make the script on x.x.x.x pipe all the data to the script on y.y.y.y, goto www.perl.com and search for pipe or piping

You have to experiment, if you want, email me and we'll discuss this issue. dax@konqueror.net

about uploading text and binary, just do a simple test on the data, if it contains binary data, then save it with binmode(), otherwise dont use binmode()...

another trick you could use is, search through the data (string) by char (character -> single letter/symbol/number) then check if the char is text-only, ie falls within natural text limits in the ASCII codes or is within e.g. 65-90 (A-Z) and 97-122 (a-z) and 48-57 (0-9) and is not !
(If this comment was disrespectful, please report it.)

 
2/20/2004 8:35:47 AMDax Ahweng

this is annoying, i've missed the last part of my post due to truncation and typing the D+AM+N word after losing it.. anyway, 65-90, etc are ASCII codes
(If this comment was disrespectful, please report it.)

 
3/30/2004 12:02:44 AM

Worked first go for me - text files only - thanks.
(If this comment was disrespectful, please report it.)

 
4/2/2004 2:28:07 PM

does thi work with uploading images ?
(If this comment was disrespectful, please report it.)

 
4/3/2004 9:08:43 AMDax Ahweng

yes, that's exactly what the example is about, uploading a jpg file...

i naively thought others reading this would be clever enough to be able to find the filename by themselves and understand everything, because it doesnt get any more fundamental than this!!! but oh well...
(If this comment was disrespectful, please report it.)

 
5/23/2004 12:49:42 PM

OK, I have a problem with binmode(FILE).
I open a .jif image file and then set the binary
mode on.....

open(IMAGE, "binmode(IMAGE);
$data = ;
.......
But it only reads in the first 39 bytes. What am I doing wrong? Can you help
(If this comment was disrespectful, please report it.)

 
5/23/2004 1:08:51 PMDax Ahweng

yes, you are doing
$data = ;
this copies what it thinks is a varialbe, e.g. a line of the image file...

what you have to do is assign it to an array, e.g.

$data =
(If this comment was disrespectful, please report it.)

 
5/23/2004 1:10:01 PMDax Ahweng

$data = "";

@data = ;

foreach (@data){
$data .= $_;
}

to transfer the data from the array @data to the string $data
(If this comment was disrespectful, please report it.)

 
6/29/2004 10:15:43 AM

### These two lines delete the boundary and file info which comes with the formfeed and leaves only the binary data
splice(@inx,0,4);
splice(@inx,$#inx,1);
$in = join("",@inx);
$in = substr($in,0,length($in) - 2);;

With reference to the code above, would you mind explaining exactly what is being spliced out of the file in the top 2 lines? From my understanding, it seems that the first 4 ‘elements’ are been taken and then the very last ‘element’. What is it that is held in these locations? I know the comment says file info and boundary, but im not sure what these mean.

Also, what units are the elements? Bytes?

Graham
(If this comment was disrespectful, please report it.)

 
6/29/2004 10:16:07 AM

Im not sure what the last line here is doing, it seems that it is removing the last 2 ‘elements’ of the file, but I assume I am mistaken, otherwise you could have just done this using splice.

Additionally, Im confused by the use of , when the filename has been passed as a CGI parameter, have I missed something?

Many thanks in advance, Graham

(If this comment was disrespectful, please report it.)

 
6/29/2004 1:21:06 PMDax Ahweng

first... the filename is part of what is spliced... hence it's not passed, is a handle to read the formdata from the previous html page...

the last two lines re-joins the data because it is originally in an array of 'lines' of data... and i 'think' the last line removes the last two characters which would be char 10 & 13, newline and carriage-return...

to answer your previous question - an element in this case is a line of data.
you got the algebra right.. i take out a couple of the first few 'lines' and the last line...
these are boundary data... a boundary is at the top and bottom of the data, it 'engulfs' the data, and contains information such as filename (which i throw away cause it's irrelevant), filesize, and a bunch of other information... e.g.
(If this comment was disrespectful, please report it.)

 
6/29/2004 1:21:30 PMDax Ahweng

e.g.

----- Boundary 1axyz -----
- Type: Text/Information -
- Length: x Characters -
- Author: Dax Ahweng -
--------------------------
Hi, this is the data, it c
an be text or binary or wh
atever...
----- End of Boundary ----

do you understand?
(If this comment was disrespectful, please report it.)

 
6/29/2004 1:52:44 PMDax Ahweng

the boundary should end like this:

-----End-----

or

-------------
(If this comment was disrespectful, please report it.)

 
6/29/2004 4:47:16 PM

Yes, that makes sense, thanks for your swift response.
(If this comment was disrespectful, please report it.)

 
7/1/2006 10:46:23 AMChethan raj

Hello Dax Ahweng ,
Thanks for the excellent simple perl script.I am beginner in perl, and i want the above code to work for multiple files with the filenames sent by the client.

Plz help
(If this comment was disrespectful, please report it.)

 

Add Your Feedback
Your feedback will be posted below and an email sent to the author. Please remember that the author was kind enough to share this with you, so any criticisms must be stated politely, or they will be deleted. (For feedback not related to this particular code, please click here instead.)
 

To post feedback, first please login.