http://www.perlmonks.org?node_id=251025

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

I'm confused as to where the file for an uploaded file is written to, the OPEN function always fails on me. I always get file permission problem or file or directory does not exist. I'm using Mac OS X's built in Apache Server. I'm unclear as to the structure of where files will be uploaded and how to write it to a directory such as the directory is located in /Library/WebServer/Documents/fileuploads/
#!/usr/bin/perl use CGI; $q = new CGI; print $q->header, $q->start_html(-title=>"Upload Results",-bgcolor=>"w +hite"); print $q->h2("Upload Results"); $file = $q->param("upfile"); if (!$file) { print "Nothing uploaded?<p>\n"; } else { print "Filename: $file<br>\n"; $ctype = $q->uploadInfo($file)->{'Content-Type'}; print "MIME Type: $ctype<br>\n"; #where is ">$file" going to be written to? and how to set to differen +t directory? open(OUT,">$file") or dienice("Can't open outfile for writing: $!" +); $flen = 0; while (read($file,$i,1024)) { print OUT $i; $flen = $flen + 1024; if ($flen > 5120000) { close(OUT); dienice("Error - file is too large. Save aborted.<p>"); } } close(OUT); print "Length: ",$flen/1024,"Kb<p>\n"; print "File saved!<p>\n"; # display the image. this only works because we have a symlink from # tmp.gif/jpeg in the current directory, to /tmp/outfile. if ($ctype eq "image/gif") { print "Here's what you sent:<p>\n"; print "<img src=\"tmp.gif\" border=1><p>\n"; } elsif ($ctype eq "image/jpeg") { print "Here's what you sent:<p>\n"; print "<img src=\"tmp.jpg\" border=1><p>\n"; } } $q->end_html; sub dienice { my($msg) = @_; print "<h2>Error</h2>\n"; print "$msg<p>\n"; exit; }

Replies are listed 'Best First'.
Re: CGI to upload file can't access filehandle
by perlplexer (Hermit) on Apr 16, 2003 at 20:28 UTC
    It's up to you where you put the file. And you really need to read CGI.pm docs!

    "$q->param('upfile');" gives you the file name on the remote PC. What you need is "$q->upload();", which returns an open file handle to a local copy of the uploaded file. You can then binmode() and read() using that file handle.

    --perlplexer
Re: CGI to upload file can't access filehandle
by dws (Chancellor) on Apr 16, 2003 at 20:22 UTC
    My upload script does
    (my $name = $filename) =~ s/^.*(\/|\\)//; open(UPLOAD, ">$UPLOADDIR/$name") or die "$name: $!";; while ( <$filename> ) { s/\r//g if $stripCRs; print UPLOAD $_; } close(UPLOAD);
    where $filename corresponds to your $upfile. I suspect that you might have junk in the filename that you need to strip out.

Re: CGI to upload file can't access filehandle
by crenz (Priest) on Apr 16, 2003 at 20:24 UTC

    Update: Whooops. Slight misunderstanding :) I guess your problem is that the filename contains invalid characters, or that the webserver does not have write permissions for the directory you are trying to write to (ie., the current directory, since you neglected to change the filename to something appropriate).

    CGI.pm stores the uploaded file in a temporary directory (probably /tmp). That means, once you query the parameter, the file is already saved on disk.

    You are supposed to read from the file and use the data for whatever you need it for or save it to a different file, in a location you like. The CGI.pm documentation gives the following example:

    # Read a text file and print it out while (<$filename>) { print; }

    or

    # Copy a binary file to somewhere safe open (OUTFILE,">>/usr/local/web/users/feedback"); while ($bytesread=read($filename,$buffer,1024)) { print OUTFILE $buffer; }

    Search for "-private_tempfiles" in the documentation to find out more about how to change the location of the temporary files.