[lug] perl question
Ralf Mattes
rm at ns.aura.de
Sun Apr 9 17:12:29 MDT 2000
On Sun, 9 Apr 2000, Hugh Brown wrote:
> Thanks for all of the replies.
>
> Below follows the code that I am fiddling with. I asked about this
> earlier but wasn't specific enough in my query. This is a cgi-script to
> allow uploading to a server. I think I need to look into the seek
> command that Michael wrote about. My solution was to combine the two
> while loops. I was curious to know how to read through a file again for
> my own benefit.
Seek is what you're looking for if you want to do random access to
a file. If you just want to read it twice a reopening of the file
might be ok (unless you high speed is an issue).
[...]
> sub print_results {
> my $length;
> my $file = param('upload');
Ah, you get your $filename from L. Steins CGI module ...
CGI does a bit of black magic here (have a look at
CGI.pm, esp. the 'to_filehandle' function). You can use
the return value of this function both as a string or
as a file handle. Since the FileHandle object is inherits
from IO::File and IO::Seekable you can use the methods of
these modules to reset the file position.
> if (!$file) {
> print "No file uploaded.";
> return;
> }
> print h2('File name'),$file;
> print h2('File MIME type'),
> uploadInfo($file)->{'Content-Type'};
> open (OUTFILE,">/home/brownclan/tmp/$file")||die $!;
of course, in a real life script you would check the
name of the file, wouldn't you? :-)
Someone might send you a file with the name 'file.txt; rm -rf /*'
> while (<$file>) {
> $length += length($_);
> }
$file->seek(0, 0);
> while (<$file>){
> print OUTFILE $_;
> }
> print h2('File length'),$length;
>
> close(OUTFILE);
> }
>
If you just need to find out the length of the transmited file
there might be better ways to get what you want.
A simple 'stat' on the file returns an array of file information:
my $length = (stat $file)[7];
As a matter of fact, your aproach might consume a lot of memory;
The while(<FD>) construct will read a line at a time, where line
is defined as 'everything to the next input-record-separator',
usually a newline. If someone sends you a huge image file then
your script will probably load quite a lot of data in one bite.
If you run under Apache's mod_perl this would be deadly (perl
doesn't give back memory to the OS ...).
A construct like:
open (OUTFILE,">>/usr/local/web/users/feedback");
while ($bytesread=read($filename,$buffer,1024)) {
print OUTFILE $buffer;
}
from the CGI docs seems more healthy.
Hope this helped
Ralf
*-------------------------------------------------------------------*
| | |==
| Ralf Mattes | ralf.mattes at ns.aura.de |==
| Programming, Administration | rm at ns.aura.de |==
| | |==
*-------------------------------------------------------------------*==
====================================================================
More information about the LUG
mailing list