Reputation: 6052
I am trying to do a simple upload of a .csv file and save it on my server. I'm not an expert in HTML or Perl, but due to client constraints this is what I must do.
Here is the HTML:
<form action="/path/to/service" target="_self" method="POST" enctype="multipart/form-data">
File: <input type="file" name="attachment" size="50">
<SUBMIT_RESET Upload File>
</form>
The Perl code looks like this:
my $sql = "SELECT NOW()";
my $date = $DB->get_field($sql);
my ($path, $ext) = split(/\./, $in{'attachment'});
my @pathParts = split(/\//, $path);
my $filename = $pathParts[@pathParts - 1] . " - " . $date;
if ($ext eq "csv") {
open (OUTFILE, ">", "$datadir/imports/" . $filename . "." . $ext);
while (read($in{'attachment'}, $buffer, 1024)) {
$file .= $buffer;
}
print OUTPUT $file;
close (OUTFILE);
}
Can anyone please give me some direction as to what I'm doing wrong. I get the file located at the correct path, but it's always empty.
Now, the code base I'm dealing with here is horrible and I cannot use strict.
Suggestions?
EDIT1: To attempt to answer how $in{'attachment'} is populated I've included a snippet of code of how forms are handled.
if ($ENV{'CONTENT_TYPE'} =~ m#^multipart/form-data#) {
my $cgi = new CGI;
my @names = $cgi->param;
foreach $name (@names) {
my @value = $cgi->param($name);
if (scalar(@value) > 1) {
foreach $val (@value) {
$in{$name} .= $val."\0";
}
$in{$name} =~s/\\0$//;
} else {
my $value = $cgi->param($name);
#my $value = join "\0", @value;
$in{$name} = $value;
}
#my $value = $cgi->param($name);
#my $value = join "\0", @value;
#$in{$name} = $value;
}
EDIT2:
To summarize the solution provided by ikegami...
I missed that the file handles were different for the read and print statements - OUTFILE
and OUTPUT
. Clearly that is completely a novice mistake and for that I apologize!
Best wishes to all who tried to help me.
Upvotes: 2
Views: 5630
Reputation: 45
HTML code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>File Upload</title>
</head>
<body>
<form action="upload.cgi" method="post" enctype="multipart/form-data">
<p>Photo to Upload: <input type="file" name="photo" /></p>
<p><input type="submit" name="Submit" value="Submit Form" /></p>
</form>
</body>
</html>
Perl Code under the file name upload.cgi:
#!C:\Program Files\perl\bin\perl.exe
use strict;
use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;
$CGI::POST_MAX = 1024 * 5000;
my $safe_filename_characters = "a-zA-Z0-9_.-";
my $upload_dir = "fileUpload/";
my $query = new CGI; my $filename = $query->param("photo");
if ( !$filename )
{
print $query->header ( );
print "There was a problem uploading your photo (try a smaller file).";
exit;
}
my ( $name, $path, $extension ) = fileparse ( $filename, '..*' );
$filename = $name . $extension;
$filename =~ tr/ /_/; $filename =~ s/[^$safe_filename_characters]//g;
if ( $filename =~ /^([$safe_filename_characters]+)$/ )
{
$filename = $1;
} else {
die "Filename contains invalid characters";
}
my $upload_filehandle = $query->upload("photo");
open ( UPLOADFILE, ">$upload_dir/$filename" ) or die "$!";
binmode UPLOADFILE;
while ( <$upload_filehandle> )
{
print UPLOADFILE;
}
close UPLOADFILE;
print $query->header ( );
print <<END_HTML;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Thanks!</title>
<style type="text/css">
img {border: none;}
</style>
</head>
<body>
<p>Thanks for uploading your photo!</p>
</body>
</html>
END_HTML
I did not write this code, but it did help me alot. I hope it helps you as well. What made this code work for me was getting the path to perl.exe right.
Upvotes: 0
Reputation: 386676
You shouldn't be using global variables. If your file handles had been lexical variables (supported since 2000!) and if you had been using use strict;
(also supported since 2000, if not earlier!), you would have found the problem:
You're not using the right variable in your print
call.
open (OUTFILE, ">", "$datadir/imports/" . $filename . "." . $ext);
print OUTPUT $file;
When I discovered the problem, I was about to recommend you find out what error you actually got:
open(my $OUTFILE, ">", "$datadir/imports/$filename.$ext")
or die $!;
while (1) {
my $rv = read($in{'attachment'}, my $buf, 1024);
die $! if !defined($rv);
last if !$rv;
print $OUTFILE $buf
or die $!;
}
close($OUTFILE)
or die $!;
(I was going to hypothesise that the error was "Bad file descriptor
" due to passing something that isn't a file handle to read
.)
Upvotes: 3