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

May your Wisdoms considerate themselves as deeply greeted.

I am a desperate newbie in the (most fascinating) world of Perl, so I need rather extensive help on this point.

I spend the last few weeks developping a project that parses a file in a set of SQL databases, using VisualBasic. The result is an .exe programm that I can run in a command-line style with several parameters. Now, the next step is to create a Web-interface, using Perl, that allow users to run this programm from everywhere. The server I will use runs on NT with Perl 5.6.1 for Windows.

And here comes my problem: I need to prompt the users for the input file of my programm (using an HTML form). Logically enough, I can't read this file from its current location (and the <input type="file" name="inputfile"> HTML tag provides a local filepath that is of little use), so I need to upload the file first.

The problem is, I have no hint on how to do that. I have come across the LWP module that should solve my case, but I can't see how to use it to upload the client-side file on my server, so that my programm can use it... Can you please describe shortly the several steps necessary for this?

Thank you.
  • Comment on Uploading files (total newbie needs help...)

Replies are listed 'Best First'.
Re: Uploading files (total newbie needs help...)
by davorg (Chancellor) on Sep 17, 2001 at 15:19 UTC
Re: Uploading files (total newbie needs help...)
by cLive ;-) (Prior) on Sep 17, 2001 at 15:17 UTC
    I'm assuming you need to upload a file to the server and feed it to your script?

    use cgi.pm to handle your file upload, save it in a temp file, then run your program like this:

    my $reslt = `C:/path/to/prog -file=C:/path/to/file`;
    ...or whatever you need for it to work.

    Why not provide an example of how you'd run it from the dos prompt locally with a local file? Then we can help further.

    cLive ;-)

      Thanks for your answers.
      Well, I'm a very unskilled Perl-er, and my problem is not how can I run my programm, but how can I upload the input file in a temp file.

      As for the CGI.pm, there are hints into it on how to create an HTML form to upload a file, but what about how to update this very file?

      Here is how my starting page looks like:
      <p><b><i>Step 1 of 3: Select input file</i></b></p> <form action="http://path/to/my/script/step1.pl" method="POST" enctype +='multipart/form-data'> <table> <tr> <td><font face="Arial" size="2">Select input file:</td> <td><input type="file" name="inputfile" size='30'></td> (...) <div align="right"><input type="submit" value="Next >"></div> </form></font>
      My script step1.pl looks like this:
      #! perl.exe use strict; use CGI; my $q = new CGI; my $file = $q->param('inputfile'));
      and so on. What should I do now with $file?

      Thanks
        As for the CGI.pm, there are hints into it on how to create an HTML form to upload a file, but what about how to update this very file?

        Keep reading. It's all there in the docs.


        When the form is processed, you can retrieve the entered filename by calling param():

        $filename = $query->param('uploaded_file');

        Different browsers will return slightly different things for the name. Some browsers return the filename only. Others return the full path to the file, using the path conventions of the user's machine. Regardless, the name returned is always the name of the file on the user's machine, and is unrelated to the name of the temporary file that CGI.pm creates during upload spooling (see below).

        The filename returned is also a file handle. You can read the contents of the file using standard Perl file reading calls:

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

        However, there are problems with the dual nature of the upload fields. If you use strict, then Perl will complain when you try to use a string as a filehandle. You can get around this by placing the file reading code in a block containing the no strict pragma. More seriously, it is possible for the remote user to type garbage into the upload field, in which case what you get from param() is not a filehandle at all, but a string.

        To be safe, use the upload() function (new in version 2.47). When called with the name of an upload field, upload() returns a filehandle, or undef if the parameter is not a valid filehandle.

        $fh = $query->upload('uploaded_file'); while (<$fh>) { print; }

        This is the recommended idiom.

        When a file is uploaded the browser usually sends along some information along with it in the format of headers. The information usually includes the MIME content type. Future browsers may send other information as well (such as modification date and size). To retrieve this information, call uploadInfo(). It returns a reference to an associative array containing all the document headers.

        $filename = $query->param('uploaded_file'); $type = $query->uploadInfo($filename)->{'Content-Type'}; unless ($type eq 'text/html') { die "HTML FILES ONLY!"; }
        --
        <http://www.dave.org.uk>

        Perl Training in the UK <http://www.iterative-software.com>

        Here is a snippet of code that should do just as you ask - You will obviously need to cater it to your needs, but should give you a starting point:

        #!/usr/bin/perl use CGI; use IO::File; use POSIX; use strict; my $cgi = CGI->new; # temporary file name is supplied by POSIX::tmpnam function my $buffer; my $tmpfile = POSIX::tmpnam; # loop through CGI handle and write new temporary file my $fh = IO::File->new(">".$tmpfile); print $fh $buffer while (read($cgi->param('inputfile'), $buffer, 1024) +); $fh->close; # retrieve file name from CGI file field parameter my $newfile = ($cgi->param('inputfile') =~ /^((?:.*[:\\\/])?)(.*)/s)[1 +]; # rename file unless file exists rename $tmpfile, $newfile unless -e $newfile; # return HTML headers and page data . . exit 0;

         

        Ooohhh, Rob no beer function well without!