Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Cgi pm and photo uploads

by julieowen24 (Novice)
on Oct 04, 2003 at 19:08 UTC ( #296565=perlquestion: print w/replies, xml ) Need Help??

julieowen24 has asked for the wisdom of the Perl Monks concerning the following question:


I am trying (very hard) to create a page where users of my site can upload there own photos, I have a few books on perl and CGI's to help me. I have managed to get a normal form to work fine and email to me, so I assume I have all the necessary things to make an upload page.

I have used the tutorial out of the book this is my form

<html><head><title>Uploading Files</title></head><body> <form action="/cgi-bin/uploading.cgi"method="post" enctype="multipart/ +form-data"> What file would you like to upload <input type="file"name="uploadfile"size="30"> <input type="submit"> </form></body></html>
This page works ( I think) it will allow me to browse my hard drive and select a file to upload.

The script I have done so far should do no more than print a page saying you have selected to upload xxxx file ( I got stuck at stage 2 and there are loads more stages to go before I am finished)

I then press submit and get a local 500 error, I had these when I first started my email form and it turned out that my permissions were wrong, I have checked these and the script is set to 755 and the cgi bin is set to 755, I assume this is correct. Should I have another folder I made one called uploads but it is in no way linked to this script, Or should I download a copy of CGI.PM if so to where and how do I reference to it in my program

This is my script

#!/usr/bin/perl use CGI::Carp 'fatalsToBrowser'; use strict use CGI ':standard'; print "content-type:text/html\n\n"; my $file=param('uploadfile'); if ($file) { print "<p>you want to upload <b>$file</b>"; } else { print "No file chosen"; } print '</body></html>';

it is called uploading.cgi and I have linked it from my form the same way as I have linked my form that works. The only difference is the use strict and use cgi standard. I have included use CGI::Carp 'fatalsToBrowser'; as I found this in another reply on a forum, however it didn't change anything for me.

I have a feeling and I may be way off base here it is something to do with CGI pm and perl 5, I don't have these on my bit of the server, but if I go up into the admin side I see that it is there, I thought this would mean I have access to it as this is what happened in my perl form that works. Do I have to link there some how, if so how I have looked everywhere about this PM and perl LIB to be honest I really don't understand it, I am willing to download it to my site if needs be, as long as that means I don't have to be connected for my form to work for others and if someone tells me where to put it (politely)

Please help me any and all suggestions are greatly received,

If you need further information on anything let me know, and i will post it. I have posted a lot as I don't know what is relevant and what is not to solve my problem

Edit: Added <code> tags. Minor formattings. larsen

Replies are listed 'Best First'.
Re: Cgi pm and photo uploads
by chromatic (Archbishop) on Oct 04, 2003 at 20:34 UTC

    The following line:

    use strict

    needs a semicolon at the end, unless that's a transcription error. You can check for this by running your program from the command line on a local machine (or the remote machine, if you have shell access):

    perl -cw uploading.cgi

    If that doesn't solve your problem, it's possible you have a very old or very broken Perl installation on the server. has shipped by default for many, many years.

      Thanks everyone for all your help, It turns out that chromatic was right I had missed ; after use strict ( I feel very very stupid now) I will be looking at everyones suggestions to help improve my CGI and Perl skills. Thank you all I am sure I will be back I am moving on to part 3 now.
Re: Cgi pm and photo uploads
by sulfericacid (Deacon) on Oct 04, 2003 at 19:58 UTC
    Here are a few tips before I get started.. First of all, please keep your questions short (sometimes itís difficult enough trying to find out what youíre trying to do, lengthy paragraphs just add more confusion). Also, please use <code></code> tags around all codes (whether they be HTML, CSS, Perl/CGI). Putting them in code tags makes it more legible for those who are trying to help you.

    It looks like you're on the right track. You have the HTML section of your form complete and it'll ask you to search a file on your hard drive. If you want the form to upload to your server, you have to tell it to do so (otherwise the file will just disappear after your script is done running). Below is a script I wrote a few months ago which asks the user for an image then it uploads it to a folder on your server.

    I don't like playing with separate HTML files, especially forms, so the script below makes the form for us (which you can remove that section and go with what you already have). The key part to pay attention to is:

    # open a new file and transfer bit by bit from what's in the buffe +r open( SAVED, ">>$localfile" ); # || die $!; while ( $bytesread = read( $remotefile, $buffer, 1024 ) ) { print SAVED $buffer; } close SAVED;
    This is where the dirty stuff happens! This is opening a file and transfering your uploaded image bit by bit until the end of file, then it saves this copy on your server. This might be a little confusing but this is straight from the docs from on CGI.

    Below is a complete script which asks for user input, uploads an image and stores some of that information to a database. You probably aren't looking for all of this but hopefully this gives you an idea on how to upload and transfer files from a form to your server.

    Hope this helps.

    #!/usr/bin/perl -w # # IMAGES FOLDER MUST BE CHMOD TO 777 otherwise script fails # use warnings; use CGI qw/:standard/; use POSIX; use DB_File; my %upload; my $upload = "imagegallery.db"; tie %upload, "DB_File", "$upload", O_CREAT|O_RDWR, 0644, $DB_BTREE or die "Cannot open file 'upload': $!\n"; my $mode = 0755; print header, start_html('Upload Form!'); print "Upload formats allowed: jpg, gif, bmp.<br>"; print start_form( -method => 'post', -enctype => 'multipart/form-data' ), table( Tr( td(""), td("Please keep filenames, descriptions and titles short to + preserve a more uniformed appearance (under 20 chars)"), ), Tr( td("Image Title: "), td( textfield( -name => 'title', -size => 50, -maxlength => 80 ), ), ), Tr( td("Short Description: "), td( textfield( -name => 'desc', -size => 50, -maxlength => 80 ), ), ), Tr( td("File: "), td( filefield( -name => 'upload', -size => 50, -maxlength => 80 ), ), ), Tr( td(), td( submit( 'button', 'submit' ), ) ) ), end_form(), hr; if ( param() ) { # take form data my $remotefile = param('upload'); my $desc = param('desc'); $desc =~ s/::/\&\#58\;\&\#58\;/g; # remove semicolons my $title = param('title'); $title =~ s/::/\&\#58\;\&\#58\;/g; # remove semicolons # make new variable to prevent overwriting of form data my $filename = $remotefile; # remove all directories in the file name path $filename =~ s/^.*[\\\/]//; $filename =~ s/::/\&\#58\;\&\#58\;/g; # remove semicolons foreach (keys %upload) { my ( $filename1, $title, $desc, $width, $height ) = split ( /::/, $upl +oad{$_} ); if ($filename1 eq $filename) { print qq(<font color="red">A file with that name already exists. Uplo +ad aborted.</font>); exit; } } # full file path to upload directory (must include filename) my $localfile = "/home/sulfericacid/public_html/gallery/images/$fi +lename"; # full url to upload directory (cannot include filename or an end +slash /) my $url = ""; my $type = uploadInfo($remotefile)->{'Content-Type'}; unless ( $type eq 'image/pjpeg' || $type eq 'image/gif' || $type e +q 'image/bmp') { print "Wrong! This is not a supported file type."; exit; } # open a new file and transfer bit by bit from what's in the buffe +r open( SAVED, ">>$localfile" ); # || die $!; while ( $bytesread = read( $remotefile, $buffer, 1024 ) ) { print SAVED $buffer; } close SAVED; chmod $mode, "$localfile"; # or die "can't chmod: $!"; print "-----------------------------<br>"; print qq(File was uploaded to <a href="$url\/$filename">$url\/$filename</a>) +; # required since module was not preinstalled on server use lib "/home/sulfericacid/public_html/lib/"; use Image::Info qw(image_info dim); # assigning info to a filename (better be an image) my $info =image_info("$localfile"); # if for any reason we can't open the file, this error trap should +pick it up if ( my $error = $info->{error} ) { #die "Can't parse image info: $error\n"; } # declaring the width and heighth of your image my ( $w, $h ) = dim($info); my $combo = join("::", $filename, $title, $desc, $w, $h); $upload{localtime()} = "$combo"; }

    "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

      Hello sulfericacid

      Your script is pretty easy to follow. It does the job. However, there are a few things that could be tweaked

      You might put my $localfile at the top of the script. It will be easier to find there when you move the script to another host. Generally it is best to put constants like this at the top of the script.

      You might run in taint mode (put -T on the shbang line)

      You allow some nasty chars in the user supplied filename. Evil can be done to you with more than semicolons. Better to use the regex's in perldoc perlsec to ban everything except what you explicitly allow.

      Having your images directory world writable, is a bit risky. For one thing other users on your server will be able to clobber things.

      If it is not set globally, you might also look at $CGI::POST_MAX

      Hope this is helpful

Re: Cgi pm and photo uploads
by mandog (Curate) on Oct 04, 2003 at 22:37 UTC

    As you say, you have a cgi form and script that works. Therefor perl5 and the CGI module are probably installed on your server. comes with perl.

    As chromatic observes you seem to be missing a semi-colen on your third line. As he suggests, you can confirm this if you run the script outside the CGI environment.

    btw, if you are curious as to what  perl -cw yourscript.pldoes you should consult perldoc perlrun

    If you do not have perl on your local MS windows machine. You can get it from ActiveState

    Sometimes, errors happen when you run your scripts from the server but not when you run them locally. In this case you should look at your  error.log file. This file contains errors that are not sent to the browser. (Ask your local system administrator for help in finding this file)

    In your case, your error.log file will probably contain a line something like:

    Premature end of script headers

    This is because the line:

        print "content-type:text/html\n\n";

    ... never runs to print the script headers.

Re: Cgi pm and photo uploads
by chanio (Priest) on Oct 04, 2003 at 20:41 UTC
    Sorry if I haven't understood you well.

    Let me explain you the concept of what I think that you have said:

    to upload something from any PC to a server there is a lot of magic!

    Basicaly, you need someone asking for a file from the server.

    And another one, pushing a file from the user's PC.

    To do this, you need more than an HTML form.

    That is just speaking. But you must also do something to make it happen.

    That is where perl comes as an agent from the server part.

    You don't need to have perl in the users part. Just the HTML form would do that part by fetching the file.

    After submiting the form, you need perl to handle the data being transfered. It has to read that data and write the file's content to the directory that you chose.

    # open a new file and transfer bit by bit from what's in the buffer open( SAVED, ">>$localfile" ); # || die $!; while ( $bytesread = read( $remotefile, $buffer, 1024 ) ) { print SAVED $buffer; } close SAVED;
    So your form called the perl script that you wrote and left at the server's /cgi-bin/ directory.

    That script read all the ulpoaded file and wrote it bit by bit on the directory that you chose.

    Now you need to finish the script and show the image in some new html page.

    To get your script be more than words written in a file, you need to have perl installed at the same location that you declared at the first line of your cgi script.

    You could know that it is correct if you see that perl is in the folder /usr/bin/ . If not, you could change that starting text with the name of the directory where Perl resides...

    At the command promp you should write:where perl And what you read as an answer is what you should copy at line 1

    You should read a complete book and try some examples until you get all the idea: .

      ...At the command promp you should write:where perl And what you read as an answer is what you should copy at line 1...

      FWIW, on my non-Win machines, this has always been which perl rather than where perl.

      From the man page:

      which takes a list of names and looks for the files which would be executed had these names been given as commands. Each argument is expanded if it is aliased, and searched for along the user's path.


Re: Cgi pm and photo uploads
by reclaw (Curate) on Oct 05, 2003 at 21:33 UTC

    The script I have done so far should do no more than print a page saying you have selected to upload xxxx file

    I think you need to forget about this second page. Your upload needs to be done with the form containing the <input type="file"> tag.


    Your mileage may very.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://296565]
Approved by bart
Front-paged by broquaint
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (7)
As of 2021-03-05 13:06 GMT
Find Nodes?
    Voting Booth?
    My favorite kind of desktop background is:

    Results (111 votes). Check out past polls.