Can Perl CGI.pm process Firefox <input type = "file", multiple = ""> form fields?
Firefox 3.6 introduced [several attributes on regular input elements type = "file"] ( http://hacks.mozilla.org/2009/12/multiple-file-input-in-firefox-3-6/ ).
I cannot get Perl to process these fields. I can call the field in the context of the list as follows:
my @files = $CGIobject->param("File_Input"); Quoting through this will give me the file names as strings, but nothing more.
Any suggestions are very welcome.
Here's the HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>Multiple file upload test</title> </head> <body> <form action="deliberately_obfuscated" method="post" enctype="multipart/form-data"> <input type="file" name="multiple_files" multiple="true"/> <button type="submit">Submit</button> </form> </body> </html> Here is Perl:
#!/usr/bin/perl #use strict; #use warnings; use CGI; my $CGIo = new CGI; print $CGIo->header(); @lightweight_fh = $CGIo->upload('myfiles'); # undef may be returned # if it not a # valid file handle if (@lightweight_fh) { # Upgrade the handle to # one compatible with IO::Handle: my $io_handle = $lightweight_fh->handle; open (OUTFILE,'>>','/hidden_deliberately/'); while ($bytesread = $io_handle->read($buffer,1024)){ print OUTFILE $buffer; } } script is not included
if (@lightweight_fh) { block.
I tried Data: Dumper on @lightweight_fh before the if block, and it literally doesn't print anything.
Woohoo, got this job. The problem of a large hand brake? Old version of CGI.pm! It is a shame that the CGI.pm documentation does not include notes along with features such as Introduced in Version X. Many other modules / libraries / packages do.
As it turned out, I had version 3.15, and the current one was 3.49. I even worked in strict mode. Does anyone know why Stein uses lax examples?
Here is XHTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>Multiple file upload test</title> </head> <body> <form action="deliberately_hidden" method="post" enctype="multipart/form-data"> <input type="file" name="multiple_files" multiple="true"/> <button type="submit">Submit</button> </form> </body> </html> Here's Perl:
#!/usr/bin/perl use strict; use warnings; use CGI; my $CGIo = new CGI; print $CGIo->header(); my @lightweight_fh = $CGIo->upload('multiple_files'); foreach my $fh (@lightweight_fh) { # undef may be returned if it not a valid file handle if (defined $fh) { # Upgrade the handle to one compatible with IO::Handle: my $io_handle = $fh->handle; open (OUTFILE,'>>','/deliberately_hidden/' . $fh); while (my $bytesread = $io_handle->read(my $buffer,1024)) { print OUTFILE $buffer } } } Thanks for all your help.
It doesn't look like you are following the documentation for Processing a file upload field using CGI.pm. Before we get into this, can you do this with a single file using a documented method?
Yes, perl CGI.pm can upload multiple files with firefox files
Would you like to see? Use this shortcut:
use Data::Dumper; print '<pre>', $CGIo->escapeHTML( Dumper( $CGIo ) ),'</pre>'; You will see something like:
$VAR1 = bless( { '.parameters' => [ 'filename', 'submit' ], 'use_tempfile' => 1, '.tmpfiles' => { '*Fh::fh00003temp-2.txt' => { 'info' => { 'Content-Type' => 'text/plain', 'Content-Disposition' => 'form-data; name="filename"; filename="temp-2.txt"' }, 'name' => bless( do{\(my $o = 'C:\\WINDOWS\\TEMP\\CGItemp52869')}, 'CGITempFile' ), 'hndl' => bless( \*{'Fh::fh00003temp-2.txt'}, 'Fh' ) }, '*Fh::fh00001temp-1.txt' => { 'info' => { 'Content-Type' => 'text/plain', 'Content-Disposition' => 'form-data; name="filename"; filename="temp-1.txt"' }, 'name' => bless( do{\(my $o = 'C:\\WINDOWS\\TEMP\\CGItemp52775')}, 'CGITempFile' ), 'hndl' => bless( \*{'Fh::fh00001temp-1.txt'}, 'Fh' ) } }, '.charset' => 'ISO-8859-1', 'param' => { 'filename' => [ $VAR1->{'.tmpfiles'}{'*Fh::fh00001temp-1.txt'}{'hndl'}, $VAR1->{'.tmpfiles'}{'*Fh::fh00003temp-2.txt'}{'hndl'} ], 'submit' => [ 'Process File' ] }, 'escape' => 1, '.header_printed' => 1 }, 'CGI' ); First you call the file_Input file upload field, then you call its multiple_files, then you call it myfiles - you must use the same name, this is important.
In addition, $ lightweight_fh and @lightweight_fh are two different variables, you will need
for my $lightweight_fh ( $CGIo->upload('multiple_files') ){ my $io_handle = $lightweight_fh->handle; ... } Also, you are trying to open DIRECTORY '/ hidden_deliberately /' as a file, and you are not checking for errors