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

Hi, I'm new at perl and am having some problems with uploading a file. I have the routine embedded in some code that makes a call to the database (which determines whether or not to upload a file). However the file won't upload. I have written (copied & modified) another program, upload.cgi and upload.htm, which work, but still no luck in this file. Is there a way to call a subroutine with the subroutine being in another file? Or can anyone see what is wrong here? Below is my code:

This is what is in the beginning of the file:
#!/usr/local/bin/perl -w

use DBI;
use CGI qw(:standard);

and somewhere farther down:

<font size="2") #UPLOAD THE FILE/PICTURE
open(IN, ">$file");
binmode IN;
open(OUT, ">/the/path/to/the/file/$AdsID.jpg");
while (read IN, $data, 1)
{
print OUT $data;
}
close IN;

Firstly, $AdsID.jpg has a problem (it's a variable from a database), but even with a hardcoded file name I still have problems. The problem being that file "copies" up but is of size 0. Any ideas?

Thanks
Cheryl

Replies are listed 'Best First'.
Re: Upload an image file
by tachyon (Chancellor) on Jul 05, 2001 at 23:45 UTC

    First you are opening the file '$file' for writing and this should be deleting the contents of $file because you have used >. To open a file for reading you use <$file. You are not checking to see if the files are opened successfully. You need to binmode OUT. I think you also need parens for the read within the while loop because of precedence issues. Finally you are reading the data in 1 byte at a time which is a very small buffer! 4-8-16kB chunks is much more efficient as with a 16kB buffer the script makes 16384 times less calls to the while loop and read function! Here is some code that should work for you:

    my $infile = "some file" my $outfile ="/the/path/to/the/file/$AdsID.jpg" open(IN, "<$infile") or die "Unable to open $infile for reading: Perl +says $!"; open(OUT,">$outfile") or die "Unable to open $outfile for writing: Per +l says $!"; binmode IN; binmode OUT; while (read(IN, $data, 16384)) { print OUT $data; } close OUT; close IN;

    Hope this helps

    cheers

    tachyon

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

Re: Upload an image file
by the_slycer (Chaplain) on Jul 05, 2001 at 23:20 UTC
    What the "copy up but is of size 0" typically means is that you are not writing anything to it.

    Looking at "IN" I can see why, you are opening that with a "write pipe", meaning that you are truncating your in file. Using warnings or -w should have caught this. (well, it would have caught the use of an unitialized variable in the while loop)

    So, your loop is empty, and nothing gets printed. Open with
    open (IN, "<$file") || die "Could not read $file, $!"
    Note the die statement there, that is ALWAYS a good idea when opening.
Re: Upload an image file
by wog (Curate) on Jul 05, 2001 at 23:22 UTC
    Please not only turn warnings on, but check the error log for your CGI scripts, (if you can't do that, redirect STDERR to some place you can check.) Your script should produce the warning: Filehandle IN opened only for output... which is exactly your problem.

    Additionally the File::Copy standard module is much better for this task.

    Also, why aren't you using -T?

Re: Upload an image file
by Anonymous Monk on Jul 05, 2001 at 23:37 UTC
    Even when I change that to:

    open (IN, "<$file") || die "Could not read $file, $!"

    I still get a file size of 0.....
      Then check your log! 'Could not read $file, file doesn't exist' means that you must read the file per browser-protocol and not per open.
Re: Upload an image file
by Anonymous Monk on Jul 06, 2001 at 00:58 UTC
    Thanks tachyon, that helped some an you explained it very well, but I'm still having problems.

    The problem is actually in opening the file to copy. If in the file box of the form I put in /path/to/myfile/on/the/web/server/pic.jpg rather than browse and grab a pic off of the hard drive of my Windows PC (C:\Documents and Settings) to upload to the webserver then it works great. BUt it won't open a file that is local. Any ideas? Do I need to be substituting the spaces in the windows file name first in order for it to be opened?
      Eh, are you running the program on a different machine than where the file actually resides? That's not going to work. Unless you NFS mount the remove disk or so. Or use tied file handles. But it's unlikely either the remote or the local machine are set up that way.

      Why not use the file upload routines from CGI.pm?

      -- Abigail

        Yes, the script and location that I want to put the files are on the webserver. I am running the script from my own pc.

        What can be done with file handles?

        BY upload routine I assume you mean something like:
        my $file_handle = $req->upload( $file );

        I have tried various ways and get errors with some. I think that I got that one to work eventually, sort of, since the file size still was 0.
      Here is what was in the error log:

      Could not read C:\sailboat.jpg, No such file or directory at /the/path/of/the/cgi/script.cgi line 336. Database handle destroyed without explicit disconnect.

      Please help!!!!