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

i'm really REALLY close now thanx to everyones help here at the monestary (thanx one and all...). the following code ALMOST works, but, the files i recieve are of (0)zero bytes. can someone take a breif moment to see why it 'acts' like the file gets to the script, but creates the two files of no length?
my(@fName) = ('Function','UserID','Signature','Session','Message','AUT +_File','THM_File');; $fHandle = CGI::->new(); $fCounter = 0; while ($fCounter <= 4) { $fBuffer[$fCounter] = $fHandle->param($fName[$fCounter]); $fCounter = $fCounter + 1; } $fBuffer[5] = $fHandle->upload($fName[5]); $fBuffer[6] = $fHandle->upload($fName[6]); if ($fBuffer[0] ne "Proccess") {goto BadAccess} if (length($fBuffer[1]) < 1) {goto BadAccess} if (length($fBuffer[2]) < 1) {goto BadAccess} if ($fBuffer[3] ne "thread2") {goto BadAccess} if (length($fBuffer[5]) < 5) {goto GoBack} if (length($fBuffer[6]) < 5) {goto GoBack} $fName[5] = substr($fBuffer[5], rindex($fBuffer[5], "\\") + 1); $fName[6] = substr($fBuffer[6], rindex($fBuffer[6], "\\") + 1); if (uc(substr($fName[5], length($fName[5]) - 4)) ne ".JPG") {goto GoBa +ck} if (uc(substr($fName[6], length($fName[6]) - 4)) ne ".JPG") {goto GoBa +ck} mkdir ("Gallery", 0775); mkdir ("Gallery/80x60", 0775); mkdir ("Gallery/640x480", 0775); open (OUTFILE, ">Gallery/640x480/$fName[5]"); print OUTFILE <$fBuffer[5]>; close (OUTFILE); open (OUTFILE, ">Gallery/80x60/$fName[6]"); print OUTFILE <$fBuffer[6]>; close (OUTFILE); GoBack: BadAccess: EndOfScript:


you mean there's any easier way?

Replies are listed 'Best First'.
Re: combined text&files
by theguvnor (Chaplain) on Mar 03, 2002 at 18:59 UTC
    A couple of other things could maybe be improved upon in terms of using more "natural" perlish syntax (and of course it always helps to use strict; use warnings;):

    For instance, I'd change:

    $fHandle = CGI::->new(); $fCounter = 0; while ($fCounter <= 4) { $fBuffer[$fCounter] = fHandle->param($fName[$fCounter]); $fCounter = $fCounter + 1; }
    to
    $fHandle = CGI->new(); # note you don't need the colons for (0..4) { $fBuffer[$_] = $fHandle->param($fName[$_]); }

    And why use goto when a subroutine would probably be more natural? Obviously I don't know what each section does but I would suspect that a sub could be a better answer... so I'd consider changing:

    if ($fBuffer[0] ne "Proccess") {goto BadAccess} if (length($fBuffer[1]) < 1) {goto BadAccess} if (length($fBuffer[2]) < 1) {goto BadAccess} if ($fBuffer[3] ne "thread2") {goto BadAccess}
    etc. with the following:
    BadAccess() if ( $Buffer[0] ne "Process" or length $fBuffer[1] < 1 or length $fBuffer[2] < 1 or $fBuffer[3] ne "thread2" );
    etc.

    Also, I can't help but wonder if using hashes might provide a more readable solution than using an array and referring to the properties you are expecting by number...

    These are just suggestions... as everyone knows There's More Than One Way To Do It but everytime a monk has given me a suggestion it's proven invaluable to study it even if I don't end up doing things exactly as suggested! Hope it helps.

    ..Guv

Re: combined text&files
by thpfft (Chaplain) on Mar 03, 2002 at 19:26 UTC

    I know the missing SWITCH is a style question where only the saintly or suicidal dare to prescribe - and i am not at all the former - but i must say that's some pretty baroque flow control you've got there.

    so much so that i found it rather hard to answer your question. So here, instead of the answer you wanted, is something completely different. I've yanked it out of something i use daily, but chopped it around a lot, so it's not exactly tested. Comments follow.

    #!/usr/bin/perl use strict; use Image::Size; use CGI; my $query = new CGI; my %upload_fields = ( AUT_File => { width => 640, height => 480, directory => 'Gallery/640x480', }, THM_File => { width => 80, height => 60, directory => 'Gallery/80x60', }, ); for (keys %upload_fields) { my $url = receive_upload( $query->upload($_), $upload_fields{$_} ) + if $query->param($_); # print confirmation? } # and carry on to handle rest of form. # meanwhile: sub receive_upload { my ($filehandle, $parameters) = @_; my $width = $parameters->{width}; my $height = $parameters->{height}; my $directory = $parameters->{directory}; my ($filewidth, $fileheight, $filetype) = imgsize( $filehandle ); throw_error("that's not an image file at all") unless $filewidth; throw_error("that's not our kind of image file") unless $filetype +=~ /jpeg/i || $filetype=~/png/i || $filetype=~/gif/i; throw_error("that's not the right size: we insist on $width wide b +y $height high")if $filewidth != $width || $fileheight != $height; open (OUTFILE,">$directory/$filehandle") || die ("couldn't save '$ +directory/$filehandle'; $!"); my $bytesread = 0; while ($bytesread = read($filehandle, my $buffer,1024)) { print OU +TFILE $buffer } close OUTFILE || die ("couldn't close newly uploaded file '$direct +ory/$filehandle'; $!"); return $directory/$filehandle; } sub throw_error { my $message = shift; # do something sensible with $message }

    There are only two main differences between this and your version: it checks that the uploaded file has the right attributes, and the upload routines are abstracted out: if you want to change or add to the set of files that are received, you just have to change the %upload_fields hash.

    Splitting the upload routines out into a sub like this will also make life easier later. When you come to manipulate the images rather than refusing bad ones, or want to do something cleverer to deal with duplicate filenames, you'll only have to make changes in one clearly identified place.

    i partly wrote it out this way because it illustrates a few of perl's strengths, acquaintance with which might make your life easier:

    • use strict will trap many common typos and other errors, among its many virtues
    • complex data structures - like the hash-of-hashrefs in $upload_fields - give you an economical way of passing round packages of related information, and in this case allow you to use named parameters for everything, making the code much easier to write and debug.
    • compact, natural syntax - eg throw_error($foo) unless $bar; again, it lets you write quickly and read easily.
    • special variables, eg $!: perl has lots of these powerful but enigmatic glyphs. This one comes out as the error message that was returned when the file operation you just attempted didn't work.
    • CPAN - Image::Size is doing a lot of work for you here, and its authors are keeping an eye on a lot of arcane mailing lists that you therefore don't need to follow. There are hundreds more where that came from.
    • tmtowtdi...

    ps. i probably don't want to know what kind of images are being uploaded here, do i?

    update. bit redundant, as it turns out, but hey. added some links anyway.

Re: combined text&files
by BeernuT (Pilgrim) on Mar 03, 2002 at 18:11 UTC
    Change your print OUTFILE statements to
    print OUTFILE $fBuffer[5]; print OUTFILE $fBuffer[6];
    using the <>'s is confusing it.

    -bn
Re: combined text&files
by steves (Curate) on Mar 03, 2002 at 18:18 UTC

    I was looking at the same area. But was thinking something more like this, since these are binary (image) files:

    my $data; while (read($fBuffer[5], $data, 1024)) { print OUTFILE $data; }
Re: combined text&files
by PriNet (Monk) on Mar 03, 2002 at 18:41 UTC
    thanx for the little 'kick in the tail'... i actually used steves format because they are image files. IT WORKED ! again...thanx for the help, much easier to have a little help; what used to take me weeks has rolled down to a few hours... thanx perlmonks.org...

    you mean there's any easier way?