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

I am running an Apache server on a networked machine and want to allow people browsing the intranet on that machine to copy files from their machines to a specified dir on the server machine.

I am using "multipart/form-data" encoding to get the filename and pass this to the routine. The only problem is that this returns a local path to the file on the user's machine and when they're looking at the intranet (which runs on HTTP://GIOTTO) in their browsers, this is not the path to the file relative to the CGI routine that is running the FILE::COPY. I have tried frigging it but no luck.

Also, FILE::COPY itself seems to return very little info. At the moment I am using the following code (where "recourse" is the dir I want the files to be uploaded to):

$filename = $formdata{file}; @parts = split (/\\/,$filename); $sourcefilename = @parts[$#parts]; $targetdir = "\\\\\Giotto\\recourse"; $targetfilename = "$targetdir\\$sourcefilename"; print "The target directory for this file is: $targetdir"; print "This makes the target path: $targetfilename"; use File::Copy; if (copy $filename, $targetfilename) { print "Copy complete..."; } else { print "Error"; }
Does anyone have any pearls of wisdom on this one?
Cheers

2002-05-03 Edit by Corion : Added formatting

Replies are listed 'Best First'.
Re: File::Copy across a Network
by tachyon (Chancellor) on May 03, 2002 at 11:58 UTC

    As you are running an Apache server and just want to upload files to it all you need to do is write a dozen line CGI script that uses CGI or even easier CGI::Simple to do the file upload. Something like:

    #!/usr/bin/perl -w use strict; use CGI::Simple; $CGI::Simple::DISABLE_UPLOADS = 0; # enable uploads $CGI::Simple::POST_MAX = 1_048_576; # allow 1MB uploads my $q = new CGI::Simple; my $target = '/path/to/write/file.name'; $q->param('upload_file') ? upload() : request_file(); exit; sub upload { $q->upload( 'upload_file', $target ); } sub request_file { print $q->header; print <<HTML; <HTML> <BODY> <FORM METHOD="POST" ACTION="http://localhost/cgi-bin/script.cgi"; ENCTYPE="multipart/form-data"> <INPUT TYPE="file" NAME="upload_file" SIZE="42"> </FORM> </BODY> </HTML> HTML }

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      That's fantastic. Thanks v much. Unfortunately I don't know how to call this type of script from the rest of my Perl stuff. Can you give me any tips on this? It also seems to crash unless I unclude:

      print "Content-type:text/html\n\n";

        Sorry code was bare bones (as well as untested :-). With CGI you need a valid header which I neglected with the upload sub. To call it from perl use LWP which is a perl HTTP client (effectively a very basic browser). There are a ton of LWP examples on this site, use Super Search. To call it from any client machine just use a browser and browse to the script on the server.

        sub upload { if ($q->upload( 'upload_file', $target )) { print $q->header, "Uploaded ", $q->param('upload'), "OK\n"; } else { print $q->header, "Oops!\n"; } }

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: File::Copy across a Network (or rather: File Upload with HTTP/CGI)
by bjelli (Pilgrim) on May 03, 2002 at 11:45 UTC

    <kbd>$formdata{file}</kbd> ? could it be that you are disregarding the three rules of cgi-programming ?

    1. thou shalt use CGI.pm
    2. thou shalt use CGI.pm
    3. thou shalt use CGI.pm

    Another point: I think you have mixed up file upload via HTTP and copying across a network. if you are using a browser to upload, you do not need to copy the file across the network from your perl script. it's already on your webserver, in a temporary file, it was transferred via HTTP.

    Try this:

    use CGI; use strict; my $query = new CGI; if ( $query->upload('file') ) { my ($fh,$info,$sourcefilename,$targetdir); my ($targetfilename, $type); $fh = $query->upload('file'); $info = $query->uploadInfo($fh)->{'Content-Disposition'}; $sourcefilename = "somefile.dat"; if ($info =~ m/filename="(.*?)"/) { $sourcefilename = $1; } $type = $query->uploadInfo($fh)->{'Content-Type'}; $targetdir = "\\\\Giotto\\recourse"; $targetfilename = "$targetdir\\$sourcefilename"; print "<p>The target directory for this file is: $targetdir"; print "<br>The info about this upload field was: $info"; print "<br>The original filename was : $sourcefilename"; print "<br>The type was : $type"; print "<br>This makes the target path: $targetfilename"; open(OUT, ">$targetfilename"); binmode($fh); while(<$fh>) { print OUT; } close OUT; }

    On my (Win98) Machine I get the following output:

    The target directory for this file is: \\Giotto\recourse
    The info about this upload field was: form-data; name="file"; filename="Artistic.txt"
    The original filename was : Artistic.txt
    The type was : text/plain
    This makes the target path: \\Giotto\recourse\Artistic.txt

    --
    Brigitte    'I never met a chocolate I didnt like'    Jellinek
    http://www.horus.com/~bjelli/         http://perlwelt.horus.at