Click to See Complete Forum and Search --> : CGI Perl - uploading files
yaman666
08-09-2007, 12:21 AM
I am trying to troubleshoot existing cgi/perl code, however, I come from php background and am not entirely familiar with how perl works regarding file uploads, more precicely - where do they go? Which temporary directory? Is there a parameter somewhere, similar to upload_tmp_dir for php?
The problem is that trying to read uploaded file returns false.
# prints proper filename
print $upload_filehandle;
$upload_filehandle = $query->upload("upload_field");
# never executes, 'while' returns false
while ( <$upload_filehandle> )
{
}
# 'read' also returns false
read($upload_handle, $buffer, 1024);
Thanks a lot!
dragle
08-09-2007, 11:33 AM
Hi,
By your code, I'm assuming you're using the CGI module. Does your form have an
enctype='multipart/form-data'
attribute? It's required for the scripts to receive the file upload data.
If your form does have that attribute, then you may need to provide us with more details to get to an answer.
Assuming a basic form that looks something like this:
<form action='/cgi-bin/uploadtest' method='post'
enctype='multipart/form-data'>
<input type='file' name='inbound' /><br />
<input type='submit' value='Submit' />
</form>
then a basic structure like this should work:
#!/usr/bin/perl -T
use strict;
use CGI ();
my $cgi = CGI->new();
print $cgi->header;
print $cgi->start_html(-title => 'Upload Test');
print '<pre>';
my $fh = $cgi->upload('inbound');
if ($fh) {
while (<$fh>) {
print;
}
close $fh;
}
else {
print "Uploaded file cannot be read.\n";
}
print '</pre>';
print $cgi->end_html;
'Course, you'd need to amend that as it does no data checking, but that's the basic idea. If you haven't already, also see the 'CREATING A FILE UPLOAD FIELD' section of the CGI docs: http://perldoc.perl.org/CGI.html#CREATING-A-FILE-UPLOAD-FIELD
Good luck!
yaman666
08-09-2007, 01:20 PM
Does your form have an
enctype='multipart/form-data'
attribute? It's required for the scripts to receive the file upload data.
Yes it does.
Assuming a basic form that looks something like this:
<form action='/cgi-bin/uploadtest' method='post'
enctype='multipart/form-data'>
<input type='file' name='inbound' /><br />
<input type='submit' value='Submit' />
</form>
then a basic structure like this should work:
#!/usr/bin/perl -T
use strict;
use CGI ();
my $cgi = CGI->new();
print $cgi->header;
print $cgi->start_html(-title => 'Upload Test');
print '<pre>';
my $fh = $cgi->upload('inbound');
if ($fh) {
while (<$fh>) {
print;
}
close $fh;
}
else {
print "Uploaded file cannot be read.\n";
}
print '</pre>';print $cgi->end_html;
And this script fails on while (<$fh>) {
Hence my thinking that it has something to do with the directory where the files get saved temporarily when they are uploaded. I did follow the tutorials, just like you described, and they all fail while trying to read the actual file, even though they can read the filename fine, i.e. print $fh; does print out the filename you submitted.
dragle
08-09-2007, 04:12 PM
Hmmmmm... according to the docs, the temp directory should only be selected if it is both a directory and is writable:
The temporary directory is selected using the following algorithm:
1. if the current user (e.g. "nobody") has a directory named
"tmp" in its home directory, use that (Unix systems only).
2. if the environment variable TMPDIR exists, use the location
indicated.
3. Otherwise try the locations /usr/tmp, /var/tmp, C:\temp,
/tmp, /temp, ::Temporary Items, and \WWW_ROOT.
Each of these locations is checked that it is a directory and is
writable. If not, the algorithm tries the next choice.
However, I noticed that in my CGI.pm (and in the one on CPAN) the user-specific tmp directory (number 1. above) is commented out.
You might also peek at cgi_error(), $CGI::DISABLE_UPLOADS and $CGI::POST_MAX, to ensure they are not set or not set too low. However, in each of those cases I believe upload() would just return an undef if they're actually causing the trouble.
dragle
08-09-2007, 04:23 PM
Oh, you you should be able to get a more direct answer to your
question by printing out the $CGITempFile::TMPDIRECTORY variable, which
is where the CGI module actually ends up storing the directory it chooses.
yaman666
08-15-2007, 08:39 PM
It is a problem with temp directory. The entire /var/tmp doesn't seem to allow to write files.
While that's being troubleshot, where exactly can I find CGI.pm to modify the temp directory in the meantime?
This is a hosted solution, so I don't have access to most of the server. Don't have access to apache configuration for example.
Thanks!
dragle
08-16-2007, 09:30 AM
You should just be able to set the TMPDIRECTORY directly within your code if you want to override it:
#!/usr/bin/perl -T
use strict;
use CGI ();
# Force the temporary files directory to /usr/tmp
$CGITempFile::TMPDIRECTORY = '/usr/tmp';
my $cgi = CGI->new();
print $cgi->header;
print $cgi->start_html(-title => 'CGI Information');
print '<pre>';
print 'TMPDIRECTORY is set to: ', $CGITempFile::TMPDIRECTORY, "\n";
# This will be the location of the CGI module on this system
print 'and CGI.pm is at: ', $INC{'CGI.pm'}, "\n";
print '</pre>';
print $cgi->end_html;
But be warned: this direct setting of the TMPDIRECTORY is undocumented in the CGI.pm pod (i.e., it could change at any time), so do this at your own risk.
Good luck!
yaman666
08-16-2007, 12:59 PM
That worked, thanks a lot!