[32657] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 3933 Volume: 11

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Apr 25 18:14:24 2013

Date: Thu, 25 Apr 2013 15:14:07 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Thu, 25 Apr 2013     Volume: 11 Number: 3933

Today's topics:
    Re: Ascertaing uploaded file size <Joey@still_Learning.invalid>
    Re: Ascertaing uploaded file size <ben@morrow.me.uk>
    Re: Ascertaing uploaded file size <Joey@still_Learning.invalid>
    Re: Ascertaing uploaded file size <ben@morrow.me.uk>
    Re: Ascertaing uploaded file size <rweikusat@mssgmbh.com>
    Re: Ascertaing uploaded file size <Joey@still_Learning.invalid>
    Re: Ascertaing uploaded file size <Joey@still_Learning.invalid>
    Re: Ascertaing uploaded file size <derykus@gmail.com>
    Re: Ascertaing uploaded file size <derykus@gmail.com>
    Re: Ascertaing uploaded file size <hjp-usenet3@hjp.at>
    Re: Ascertaing uploaded file size <Joey@still_Learning.invalid>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Wed, 24 Apr 2013 15:01:14 -0700
From: "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>
Subject: Re: Ascertaing uploaded file size
Message-Id: <gglgn81oi2vaosajjf6h22ur1t201s6vca@4ax.com>

Ben Morrow wrote:
>
>> On 2013-04-24, Joey@still_Learning.invalid <Joey@still_Learning.invalid> wrote:
>> >  I decided it was safest to test files after all files were
>> > uploaded. 
>> 
>I get the impression (though this is incredibly unclear) that the OP is
>not in control of the client, and this is a piece of server-side code to
>accept an upload from a web browser. While it is possible (at least with
>really modern browsers) to MD5 or SHA1 a file before uploading it, using
>newish JavaScript APIs for reading the files, the OP hasn't given me the
>impression that is what he is trying to do.
>
Indeed this is a piece of server-side code that accepts a multi-file
upload from a web browser. 

What I ended up doing was upload all files to the server and then using a
filename as a key, I search the server directory at $filepath and compare
the actual size of the uploaded file to the size of the file submitted for
upload:

 ...uploaded all files to server...
Array of files submitted to server-side Perl script = @uploadFiles
Path to files uploaded to server = $filepath
Number of files submitted = $imgCnt

 ...close UPLOADFILE

for (my $j = 0;  $j < $imgCnt; $j++) {
$filename = $uploadFiles[$j];
$filesize = -s $filename

opendir DH, $filePath or die "Can't opendir $filePath $!";
while (my $serverFileName = readdir DH) {
$serverFileSize = -s $serverFileName;
if (($serverFileName eq $filename) && ($filesize == $serverFileSize)) {
$numFilesReceived++;
}}}
if ($numFilesReceived != $imgCnt) {$uploadErrorFlag = 1;}

BTW, I have a specific purpose in using the loop syntax shown [instead of
'for my $filename (@uploadFiles)']
 
Thanks again for the help.
-- 
Joey


------------------------------

Date: Thu, 25 Apr 2013 00:39:44 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Ascertaing uploaded file size
Message-Id: <037m4a-fma1.ln1@anubis.morrow.me.uk>


Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
>
> Indeed this is a piece of server-side code that accepts a multi-file
> upload from a web browser. 
> 
> What I ended up doing was upload all files to the server and then using a
> filename as a key, I search the server directory at $filepath and compare
> the actual size of the uploaded file to the size of the file submitted for
> upload:

Either you are still missing something here, or I am, I'm not sure
which. The only way I can make sense of what you're saying is if the
server and the client (browser) are on the same machine, and this is
some sort of test rig to check the upload is behaving properly: is
that what you're doing? If so it would have been helpful to say so,
since that isn't exactly a very common situation.

If not, then your comparison still isn't accomplishing anything, because
you still don't have access to the files the client was trying to
upload.

> ...uploaded all files to server...
> Array of files submitted to server-side Perl script = @uploadFiles
> Path to files uploaded to server = $filepath
> Number of files submitted = $imgCnt
> 
> ...close UPLOADFILE
> 
> for (my $j = 0;  $j < $imgCnt; $j++) {
> $filename = $uploadFiles[$j];
> $filesize = -s $filename
> 
> opendir DH, $filePath or die "Can't opendir $filePath $!";

    opendir my $DH, $filePath or die ...;

> while (my $serverFileName = readdir DH) {
> $serverFileSize = -s $serverFileName;

This is a classic mistake: the filenames returned from readdir are
relative to the directory you opened, so you need to qualify them with
$filePath to make them usable. As this stands the two -ss will stat the
same file, making the whole exercise rather pointless.

> if (($serverFileName eq $filename) && ($filesize == $serverFileSize)) {

You are reopening and rereading the entire directory for every file,
which is completely unnecessary. In fact, you don't need to read the
directory at all, since you already know which file you are looking for;
you can distinguish between 'a file which isn't there' and 'a file of
size 0' because -s returns undef if the file doesn't exist.

> $numFilesReceived++;
> }}}
> if ($numFilesReceived != $imgCnt) {$uploadErrorFlag = 1;}
> 
> BTW, I have a specific purpose in using the loop syntax shown [instead of
> 'for my $filename (@uploadFiles)']

And what would that be?

Ben



------------------------------

Date: Wed, 24 Apr 2013 18:09:19 -0700
From: "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>
Subject: Re: Ascertaing uploaded file size
Message-Id: <9uugn85vpu1qfk3bnjbrccbvjvgj79sr91@4ax.com>

Ben Morrow wrote:

>
>Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
>>
>> Indeed this is a piece of server-side code that accepts a multi-file
>> upload from a web browser. 
>> 
>> What I ended up doing was upload all files to the server and then using a
>> filename as a key, I search the server directory at $filepath and compare
>> the actual size of the uploaded file to the size of the file submitted for
>> upload:
>
>Either you are still missing something here, or I am, I'm not sure
>which. The only way I can make sense of what you're saying is if the
>server and the client (browser) are on the same machine, and this is
>some sort of test rig to check the upload is behaving properly: is
>that what you're doing? If so it would have been helpful to say so,
>since that isn't exactly a very common situation.

I'm sure not communicating... I'm equally sure a mea culpa is in order.
Sorry.

I am simply uploading a group of files selected by the user to a server
through a web browser and I want to verify that the number of files
selected were indeed uploaded and are stored on the server. To accomplish
this, I check the known file sizes of the files before and after they're
uploaded to the server.
>
>If not, then your comparison still isn't accomplishing anything, because
>you still don't have access to the files the client was trying to
>upload.

HTML5 Forms and client-side javascript enable the capture of filenames,
size and other parameters of the multiple files selected for upload and
submitted to the perl script. My perl script has all the information about
the files intended for upload and can easily compare that information with
the parameters of files stored on the server, e.g., file size.
>
>> ...uploaded all files to server...
>> Array of files submitted to server-side Perl script = @uploadFiles
>> Path to files uploaded to server = $filepath
>> Number of files submitted = $imgCnt
>> 
>> ...close UPLOADFILE
>> 
>> for (my $j = 0;  $j < $imgCnt; $j++) {
>> $filename = $uploadFiles[$j];
>> $filesize = -s $filename
>> 
>> opendir DH, $filePath or die "Can't opendir $filePath $!";
>
>    opendir my $DH, $filePath or die ...;

OK. 
>
>> while (my $serverFileName = readdir DH) {
>> $serverFileSize = -s $serverFileName;
>
>This is a classic mistake: the filenames returned from readdir are
>relative to the directory you opened, so you need to qualify them with
>$filePath to make them usable. As this stands the two -ss will stat the
>same file, making the whole exercise rather pointless.

Interesting, as that's apparently not what is happening. [After you
pointed out my same-file comparison gaffe yesterday] I tested to assure
that I was indeed comparing against the proper files. I changed file sizes
on the server files and then ran the script with hard-coded submitted file
parameters. The script correctly identified files of different sizes.
Perhaps re-opening the folder is setting its path as the default?
>
>> if (($serverFileName eq $filename) && ($filesize == $serverFileSize)) {
>
>You are reopening and rereading the entire directory for every file,
>which is completely unnecessary. In fact, you don't need to read the
>directory at all, since you already know which file you are looking for;
>you can distinguish between 'a file which isn't there' and 'a file of
>size 0' because -s returns undef if the file doesn't exist.

I'm not reopening, but yes, I'm rereading the entire directory. Your
suggested change is welcome. Thanks.
>
>> $numFilesReceived++;
>> }}}
>> if ($numFilesReceived != $imgCnt) {$uploadErrorFlag = 1;}
>> 
>> BTW, I have a specific purpose in using the loop syntax shown [instead of
>> 'for my $filename (@uploadFiles)']
>
>And what would that be?
>
Depending on which file is selected, I need to access two other arrays,
and in my fledgling perl trance, this is the easiest way I know of to
accomplish what I want.

I hope I've conveyed my approach and methodology. :-)

Again, thanks for your help.
-- 
Joey


------------------------------

Date: Thu, 25 Apr 2013 12:37:12 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Ascertaing uploaded file size
Message-Id: <84hn4a-hqc2.ln1@anubis.morrow.me.uk>


Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
> Ben Morrow wrote:
> >Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
> >>
> >> Indeed this is a piece of server-side code that accepts a multi-file
> >> upload from a web browser. 
> >> 
> >> What I ended up doing was upload all files to the server and then using a
> >> filename as a key, I search the server directory at $filepath and compare
> >> the actual size of the uploaded file to the size of the file submitted for
> >> upload:
[...]
> >
> >If not, then your comparison still isn't accomplishing anything, because
> >you still don't have access to the files the client was trying to
> >upload.
> 
> HTML5 Forms and client-side javascript enable the capture of filenames,
> size and other parameters of the multiple files selected for upload and
> submitted to the perl script. My perl script has all the information about
> the files intended for upload and can easily compare that information with
> the parameters of files stored on the server, e.g., file size.

OK, so where are these file sizes sent from the client? 

You do realise, don't you, that the code you have posted so far doesn't
upload anything, it just copies a file from one place on the server to
another? The actual upload is being done by the webserver, or CGI.pm, or
something; since you still haven't explained properly how you are
running this it's hard to tell. In fact, you almost certainly don't need
to copy the file at all: since it's already been written out on the
server you can probably just rename it to where you want it to live in
the end.

The file sizes you are comparing are the sizes before and after the
copy, which is pretty pointless since the only way they could be
different (barring a major OS bug) is if another process modified them
in the meanwhile. What's much more interesting is whether the file
written out by whatever actually did the upload is the same size as the
file the client sent; in order to test that, you need to compare a -s on
that file with a size sent by the client.

> >> while (my $serverFileName = readdir DH) {
> >> $serverFileSize = -s $serverFileName;
> >
> >This is a classic mistake: the filenames returned from readdir are
> >relative to the directory you opened, so you need to qualify them with
> >$filePath to make them usable. As this stands the two -ss will stat the
> >same file, making the whole exercise rather pointless.
> 
> Interesting, as that's apparently not what is happening. [After you
> pointed out my same-file comparison gaffe yesterday] I tested to assure
> that I was indeed comparing against the proper files. I changed file sizes
> on the server files and then ran the script with hard-coded submitted file
> parameters. The script correctly identified files of different sizes.
> Perhaps re-opening the folder is setting its path as the default?

No, definitely not. The 'default' directory is usually called the
'current working directory' or just the 'current directory'; the only
way to change it is with chdir().

I'm beginning to suspect the code you are running is not the same as the
code you are posting, since the code you are posting doesn't refer to
any client-submitted file sizes at all. Please only post code *you have
actually run*.

> >> if (($serverFileName eq $filename) && ($filesize == $serverFileSize)) {
> >
> >You are reopening and rereading the entire directory for every file,
> >which is completely unnecessary. In fact, you don't need to read the
> >directory at all, since you already know which file you are looking for;
> >you can distinguish between 'a file which isn't there' and 'a file of
> >size 0' because -s returns undef if the file doesn't exist.
> 
> I'm not reopening, but yes, I'm rereading the entire directory. Your
> suggested change is welcome. Thanks.

The opendir is inside the for loop, so you are reopening the directory
every time round that loop.

> >> $numFilesReceived++;
> >> }}}
> >> if ($numFilesReceived != $imgCnt) {$uploadErrorFlag = 1;}
> >> 
> >> BTW, I have a specific purpose in using the loop syntax shown [instead of
> >> 'for my $filename (@uploadFiles)']
> >
> >And what would that be?
> >
> Depending on which file is selected, I need to access two other arrays,
> and in my fledgling perl trance, this is the easiest way I know of to
> accomplish what I want.

OK. That's not exactly what I would call good style, but it's not an
unreasonable approach. But again: where are these other arrays? It's
extremely hard to see what's going on if you just pick out bits of code
that don't make sense on their own, and since you don't know Perl very
well yet it's quite likely that the bits you pick out will behave
differently from your real code.

Ben



------------------------------

Date: Thu, 25 Apr 2013 14:19:31 +0100
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Ascertaing uploaded file size
Message-Id: <87fvye928s.fsf@sapphire.mobileactivedefense.com>

"Joey@still_Learning.invalid" <Joey@still_Learning.invalid> writes:

[...]


> for (my $j = 0;  $j < $imgCnt; $j++) {
> $filename = $uploadFiles[$j];
> $filesize = -s $filename
>
> opendir DH, $filePath or die "Can't opendir $filePath $!";
> while (my $serverFileName = readdir DH) {
> $serverFileSize = -s $serverFileName;
> if (($serverFileName eq $filename) && ($filesize == $serverFileSize)) {
> $numFilesReceived++;
> }}}
> if ($numFilesReceived != $imgCnt) {$uploadErrorFlag = 1;}
>
> BTW, I have a specific purpose in using the loop syntax shown [instead of
> 'for my $filename (@uploadFiles)']

Even if this is so, you could use

for my $j (0 .. $imgCnt - 1) {
 .
 .
 .
 .
}

instead. IMO, you should also consider to make that

for (0 .. $imgCnt - 1) {
}

and use $_ in the loop instead of $j. Another idea would to read the
directory once into an hash:

my ($dh, %files);

opendir($dh, $filePath);
%files = map { $_, 1 } <$dh>

and then change the loop to

for (0 .. $imgCnt - 1) {
	$filename = $uploadFiles[$j];
	++numFilesReceived if $files{$filename};
}


------------------------------

Date: Thu, 25 Apr 2013 07:17:13 -0700
From: "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>
Subject: Re: Ascertaing uploaded file size
Message-Id: <71cin8pikcumqp156mi9uhlhl2n58egde3@4ax.com>

Ben Morrow wrote:

>
>Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
>> Ben Morrow wrote:
>> >Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
>> >>
>> >> Indeed this is a piece of server-side code that accepts a multi-file
>> >> upload from a web browser. 
>> >> 
>> >> What I ended up doing was upload all files to the server and then using a
>> >> filename as a key, I search the server directory at $filepath and compare
>> >> the actual size of the uploaded file to the size of the file submitted for
>> >> upload:
>[...]
>> >
>> >If not, then your comparison still isn't accomplishing anything, because
>> >you still don't have access to the files the client was trying to
>> >upload.
>> 
>> HTML5 Forms and client-side javascript enable the capture of filenames,
>> size and other parameters of the multiple files selected for upload and
>> submitted to the perl script. My perl script has all the information about
>> the files intended for upload and can easily compare that information with
>> the parameters of files stored on the server, e.g., file size.
>
>OK, so where are these file sizes sent from the client? 

Are you trying to pull my leg?

Files are selected by the user and are submitted to the server:
>
>You do realise, don't you, that the code you have posted so far doesn't
>upload anything, it just copies a file from one place on the server to
>another? The actual upload is being done by the webserver, or CGI.pm, or
>something; since you still haven't explained properly how you are
>running this it's hard to tell. In fact, you almost certainly don't need
>to copy the file at all: since it's already been written out on the
>server you can probably just rename it to where you want it to live in
>the end.

I realize nothing of the sort. I have files on my desktop machine that are
being successfully uploaded and tested for size.

Here's a snippet of the client HTML code:

<div>
<form id='form2' name='form2' action='cgi-bin/image_uploadtest.pl'
method='post' enctype='multipart/form-data' onSubmit='sendItP2()'>

<input type='file' name='myFile0[]' id='myFile0' multiple='multiple'
min='1' max='1000'>

<input type=hidden name='fileArray' value=' '>

</div>
</form>

A js event listener is employed:

fileselect = document.getElementById("myFile0");
fileselect.addEventListener("change", FileSelectHandler, false);

where (in part)::

function FileSelectHandler(e) {
	var files = e.dataTransfer.files;
	document.forms["form2"].elements["fileArray"].value = files;
	imgCnt = files.length;
	document.forms["form2"].elements["imgCnt"].value = imgCnt;
}

Files are selected by the user and passed to javascript function
'sendItP2(),' which submits the form: document.forms['form2'].submit();

At the server side the information submitted is passed:

$filePath = path to server folder where files are to be stored;
$imgCnt = param('imgCnt');
@uploadFiles = param('myFile0[]');
@upload_filehandles = $query->upload("myFile0[]");
@filesize = ();

chdir $filePath or die

for (my $i=0;$i<$imgCnt;$i++) {
	$filename = $uploadFiles[$i];
	$filesize = -s $filename;
	push(@filesize, $filesize);
	$upload_filehandle = $upload_filehandles[$i];
	$filename =~ s/.*[\/\\](.*)/$1/;
	open (UPLOADFILE, ">$filePath/$filename") or die...
	binmode UPLOADFILE; 
	while (<$upload_filehandle>) {
	print UPLOADFILE;
	}
	close UPLOADFILE or die "Can't Close. $!";
	}

At this point the selected files have all (ostensibly) been uploaded to
$filepath. Next, comes the comparison of file sizes (which hasn't yet been
corrected re your input):

	for (my $j = 0;  $j < $imgCnt; $j++) {
	$filename = $uploadFiles[$j];
	$filesize = $filesize[$j];
	opendir DH,$filePath or die "Can't opendir $filePath $!";
	while (my $serverFileName = readdir DH) {
	$serverFileSize = -s $serverFileName;
	if (($serverFileName eq $filename) && ($filesize ==
$serverFileSize)) {
	$numImagesReceived++;
	}
	}
}
	if ($numImagesReceived != $imgCnt) {$uploadErrorFlag = 1;}
}
The next block of code simply checks $uploadErrorFlag and outputs a
message based on its value.
>
>The file sizes you are comparing are the sizes before and after the
>copy, which is pretty pointless since the only way they could be
>different (barring a major OS bug) is if another process modified them
>in the meanwhile. 

Any number of problems might compromise the upload.

>What's much more interesting is whether the file
>written out by whatever actually did the upload is the same size as the
>file the client sent; in order to test that, you need to compare a -s on
>that file with a size sent by the client.

Yes, which is exactly what I believe I'm doing.
>
>> >> while (my $serverFileName = readdir DH) {
>> >> $serverFileSize = -s $serverFileName;
>> >
>> >This is a classic mistake: the filenames returned from readdir are
>> >relative to the directory you opened, so you need to qualify them with
>> >$filePath to make them usable. As this stands the two -ss will stat the
>> >same file, making the whole exercise rather pointless.
>> 
>> Interesting, as that's apparently not what is happening. [After you
>> pointed out my same-file comparison gaffe yesterday] I tested to assure
>> that I was indeed comparing against the proper files. I changed file sizes
>> on the server files and then ran the script with hard-coded submitted file
>> parameters. The script correctly identified files of different sizes.
>> Perhaps re-opening the folder is setting its path as the default?
>
>No, definitely not. The 'default' directory is usually called the
>'current working directory' or just the 'current directory'; the only
>way to change it is with chdir().

The first line in my code is chdir $filepath. Sorry I didn't show it in my
original post. I assumed that as my files were being uploaded with the
code I showed, it would be understood a change dir had been made. 
(Damn! There's that word 'assume.')
>
>I'm beginning to suspect the code you are running is not the same as the
>code you are posting, since the code you are posting doesn't refer to
>any client-submitted file sizes at all. Please only post code *you have
>actually run*.

With the exception of code that is not related to the upload itself, you
have the exact code I'm running, above.
>
>> >> if (($serverFileName eq $filename) && ($filesize == $serverFileSize)) {
>> >
>> >You are reopening and rereading the entire directory for every file,
>> >which is completely unnecessary. In fact, you don't need to read the
>> >directory at all, since you already know which file you are looking for;
>> >you can distinguish between 'a file which isn't there' and 'a file of
>> >size 0' because -s returns undef if the file doesn't exist.
>> 
>> I'm not reopening, but yes, I'm rereading the entire directory. Your
>> suggested change is welcome. Thanks.
>
>The opendir is inside the for loop, so you are reopening the directory
>every time round that loop.
>
>> >> $numFilesReceived++;
>> >> }}}
>> >> if ($numFilesReceived != $imgCnt) {$uploadErrorFlag = 1;}

My error. It is reopening with every iteration. 

I contend that the above code properly submits files selected for upload,
ascertains the file sizes, uploads the file to $filePath, and compares the
uploaded file sizes with the selected file sizes.

I have tested this by hard-coding file names and sizes to simulate form
submission, eliminating the upload process, and comparing hard coded
parameters with the files previously uploaded and stored on the server. If
the file size of the uploaded files is different from the hard-coded
values, I detect the error. It works albeit with the issues you originally
highlighted.
>> >> 
>> >> BTW, I have a specific purpose in using the loop syntax shown [instead of
>> >> 'for my $filename (@uploadFiles)']
>> >
>> >And what would that be?
>> >
>> Depending on which file is selected, I need to access two other arrays,
>> and in my fledgling perl trance, this is the easiest way I know of to
>> accomplish what I want.
>
>OK. That's not exactly what I would call good style, but it's not an
>unreasonable approach. But again: where are these other arrays? It's
>extremely hard to see what's going on if you just pick out bits of code
>that don't make sense on their own, and since you don't know Perl very
>well yet it's quite likely that the bits you pick out will behave
>differently from your real code.
>
There's no reason to show the other arrays or the code associated with
them. They have nothing to do with the upload process.

Thanks again for taking the time to show me the way...
-- 
Joey


------------------------------

Date: Thu, 25 Apr 2013 07:19:47 -0700
From: "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>
Subject: Re: Ascertaing uploaded file size
Message-Id: <boein8dokuhul0oo9tck580hk486rs3eeo@4ax.com>

Rainer Weikusat wrote:

>"Joey@still_Learning.invalid" <Joey@still_Learning.invalid> writes:
>
>[...]
>
>
>> for (my $j = 0;  $j < $imgCnt; $j++) {
 ...<snip>
>>
>> BTW, I have a specific purpose in using the loop syntax shown [instead of
>> 'for my $filename (@uploadFiles)']
>
>Even if this is so, you could use
>
>for my $j (0 .. $imgCnt - 1) {
>.
>instead. IMO, you should also consider to make that
>
>for (0 .. $imgCnt - 1) {
>}
>
>and use $_ in the loop instead of $j. Another idea would to read the
>directory once into an hash:
>
>my ($dh, %files);
>
>opendir($dh, $filePath);
>%files = map { $_, 1 } <$dh>
>
>and then change the loop to
>
>for (0 .. $imgCnt - 1) {
>	$filename = $uploadFiles[$j];
>	++numFilesReceived if $files{$filename};
>}
Thank you for the suggestions. More for me to ponder...
-- 
Joey


------------------------------

Date: Thu, 25 Apr 2013 13:04:49 -0700 (PDT)
From: "C.DeRykus" <derykus@gmail.com>
Subject: Re: Ascertaing uploaded file size
Message-Id: <a77ab20c-44c3-4d81-b865-ced6854fa5f3@googlegroups.com>

On Thursday, April 25, 2013 7:19:47 AM UTC-7, Jo...@still_Learning.invalid wrote:
> Rainer Weikusat wrote:
> 
> 
> 
> >"Joey@still_Learning.invalid" <Joey@still_Learning.invalid> writes:
> 
> >
> 
> >[...]
> 
> >
> 
> >
> 
> >> for (my $j = 0;  $j < $imgCnt; $j++) {
> 
> ...<snip>
> 
> >>
> 
> >> BTW, I have a specific purpose in using the loop syntax shown [instead of
> 
> >> 'for my $filename (@uploadFiles)']
> 
> >
> 
> >Even if this is so, you could use
> 
> >
> 
> >for my $j (0 .. $imgCnt - 1) {
> 
> >.
> 
> >instead. IMO, you should also consider to make that
> 
> >
> 
> >for (0 .. $imgCnt - 1) {
> 
> >}
> 
> >
> 
> >and use $_ in the loop instead of $j. Another idea would to read the
> 
> >directory once into an hash:
> 
> >
> 
> >my ($dh, %files);
> 
> >
> 
> >opendir($dh, $filePath);
> 
> >%files = map { $_, 1 } <$dh>
> 
> >
> 
> >and then change the loop to
> 
> >
> 
> >for (0 .. $imgCnt - 1) {
> 
> >	$filename = $uploadFiles[$j];
> 
> >	++numFilesReceived if $files{$filename};
> 
> >}
> 
> Thank you for the suggestions. More for me to ponder...
> 

Here's how a more idiomatic, slimmed-down, calorie-counting 
version of the code might look: 

 ...
for (0 .. $imgCnt-1) {

        open my $upload_fh, '>', "$filePath/$uploadFiles[$_]"
             or die...
        binmode $upload_fh;
        print $upload_fh while <$upload_filehandle>;
        close $upload_fh or die ...;
}

opendir my $dir_fh, $filePath  or die ...;

for (0 .. $imgCnt-1) {

        while (my $serverFileName = readdir $dir_fh) {
            $numImagesReceived++ if $serverFileName eq uploadFiles[$_]
                           and -s $serverFileName == -s $uploadFiles[$_];
        }
        seekdir( $dir_fh, 0 ) or die "seek: $uploadFiles[$_];
}
if ($numImagesReceived != $imgCnt) {$uploadErrorFlag = 1;}
 ...


-- 
Charles DeRykus


------------------------------

Date: Thu, 25 Apr 2013 13:25:00 -0700
From: Charles DeRykus <derykus@gmail.com>
Subject: Re: Ascertaing uploaded file size
Message-Id: <klc3ev$oab$1@speranza.aioe.org>

On 4/25/2013 1:04 PM, C.DeRykus wrote:
> On Thursday, April 25, 2013 7:19:47 AM UTC-7, Jo...@still_Learning.invalid wrote:
>> Rainer Weikusat wrote:
>>
>>
>>
>>> "Joey@still_Learning.invalid" <Joey@still_Learning.invalid
 ...

> Here's how a more idiomatic, slimmed-down, calorie-counting
> version of the code might look:
>
> ...

I need to slim down as well... mea culpa for the double spacing on the 
earlier post.

-- 
Charles DeRykus


------------------------------

Date: Thu, 25 Apr 2013 22:36:20 +0200
From: "Peter J. Holzer" <hjp-usenet3@hjp.at>
Subject: Re: Ascertaing uploaded file size
Message-Id: <slrnknj4u5.97c.hjp-usenet3@hrunkner.hjp.at>

On 2013-04-25 14:17, Joey@still_Learning.invalid <Joey@still_Learning.invalid> wrote:
> Ben Morrow wrote:
>
>>
>>Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
>>> Ben Morrow wrote:
>>> >Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
>>> >>
>>> >> Indeed this is a piece of server-side code that accepts a multi-file
>>> >> upload from a web browser. 
>>> >> 
>>> >> What I ended up doing was upload all files to the server and then using a
>>> >> filename as a key, I search the server directory at $filepath and compare
>>> >> the actual size of the uploaded file to the size of the file submitted for
>>> >> upload:
>>[...]
>>> >
>>> >If not, then your comparison still isn't accomplishing anything, because
>>> >you still don't have access to the files the client was trying to
>>> >upload.
>>> 
>>> HTML5 Forms and client-side javascript enable the capture of filenames,
>>> size and other parameters of the multiple files selected for upload and
>>> submitted to the perl script. My perl script has all the information about
>>> the files intended for upload and can easily compare that information with
>>> the parameters of files stored on the server, e.g., file size.
>>
>>OK, so where are these file sizes sent from the client? 
>
> Are you trying to pull my leg?
>
> Files are selected by the user and are submitted to the server:

Where are the file sizes which are submitted to the server IN YOUR CODE?

You haven't shown us any code which retrieves the parameters containing
those file sizes. Instead you have shown us this:

    for (my $j = 0;  $j < $imgCnt; $j++) {
    $filename = $uploadFiles[$j];
    $filesize = -s $filename

At this point $filesize doesn't contain a size which was possibly
captured by some javascript code on the client and submitted to the
server. It contains the size of the file $uploadFiles[$j] ON THE SERVER.

As far as I can see you haven't shown us how @uploadFiles is populated
either, so we don't know what's in that array either. It might be a
relative or absolute path name or it might be a file handle. It might
refer to a temporary file created by your request parsing module (I
think that's another piece of information you've neglected to tell us)
or it might refer to one of the files on their final destination.



>>You do realise, don't you, that the code you have posted so far doesn't
>>upload anything,

True.

>>it just copies a file from one place on the server to
>>another?

Also true.

>>The actual upload is being done by the webserver, or CGI.pm, or
>>something;

Um, I'd quibble with your terminology here. The server doesn't upload
anything. It's the client which does the uploading. The server just
receives the uploaded data (and may pass it on to a CGI script or
something).

>>since you still haven't explained properly how you are
>>running this it's hard to tell. In fact, you almost certainly don't need
>>to copy the file at all: since it's already been written out on the
>>server you can probably just rename it to where you want it to live in
>>the end.

I don't think it's safe to assume that the temporary files and the final
destination are on the same file system. (Of course File::Copy::move
will take care of that detail).


> I realize nothing of the sort.

I guess that's part of the problem.

> I have files on my desktop machine that are
> being successfully uploaded and tested for size.

Yes, but not in the code you've shown us. Both uploading and receiving
the upload is happening in code you haven't shown us. 


> Here's a snippet of the client HTML code:

Ah, now we are finally getting to see the relevant code (or at least
part of it).


><div>
><form id='form2' name='form2' action='cgi-bin/image_uploadtest.pl'
> method='post' enctype='multipart/form-data' onSubmit='sendItP2()'>
>
><input type='file' name='myFile0[]' id='myFile0' multiple='multiple'
> min='1' max='1000'>
>
><input type=hidden name='fileArray' value=' '>
>
></div>
></form>
>
> A js event listener is employed:
>
> fileselect = document.getElementById("myFile0");
> fileselect.addEventListener("change", FileSelectHandler, false);
>
> where (in part)::
>
> function FileSelectHandler(e) {
> 	var files = e.dataTransfer.files;
> 	document.forms["form2"].elements["fileArray"].value = files;
> 	imgCnt = files.length;
> 	document.forms["form2"].elements["imgCnt"].value = imgCnt;
> }

I don't see where this code "captures ... the size ... of the multiple
files", as you claimed above. It does capture the number of files,
though.


> Files are selected by the user and passed to javascript function
> 'sendItP2(),' which submits the form: document.forms['form2'].submit();
>
> At the server side the information submitted is passed:
>
> $filePath = path to server folder where files are to be stored;
> $imgCnt = param('imgCnt');
> @uploadFiles = param('myFile0[]');
> @upload_filehandles = $query->upload("myFile0[]");
> @filesize = ();

Ok, from the sub names param and upload I gather that you are using the
CGI module (The mixture of function and method calls is curious, though).

The value(s) returned by param() are magic: They contain both the 
file name sent by the client and an open file handle to the temporary
file created by CGI.pm (same as upload()).

> chdir $filePath or die
>
> for (my $i=0;$i<$imgCnt;$i++) {
> 	$filename = $uploadFiles[$i];
> 	$filesize = -s $filename;

So here you apply -s to one of these dual-valued variables. That might
either try to determine the size of a local file with the same name as
the one submitted by the client (and as you changed to directory to
$filePath that would probably be a previously uploaded one) or the size
of the temporary file which the filehandle refers to. Without having
tried it I think the latter is more likely. 

In no case does this determine the size of a file on the client. Except
of course, that the temporary file on the server should have the same
contents (and size) as the file on the client, but that's the thing you
are trying to test, so you can't assume it.

> 	push(@filesize, $filesize);
> 	$upload_filehandle = $upload_filehandles[$i];
> 	$filename =~ s/.*[\/\\](.*)/$1/;
> 	open (UPLOADFILE, ">$filePath/$filename") or die...
> 	binmode UPLOADFILE; 
> 	while (<$upload_filehandle>) {
> 	print UPLOADFILE;
> 	}
> 	close UPLOADFILE or die "Can't Close. $!";
> 	}
>
> At this point the selected files have all (ostensibly) been uploaded to
> $filepath.

More correctly: They have been uploaded to a temporary location before
your loop even started. In the loop you copied them from this temporary
location to $filepath.

> Next, comes the comparison of file sizes (which hasn't yet been
> corrected re your input):
>
> 	for (my $j = 0;  $j < $imgCnt; $j++) {
> 	$filename = $uploadFiles[$j];
> 	$filesize = $filesize[$j];
> 	opendir DH,$filePath or die "Can't opendir $filePath $!";
> 	while (my $serverFileName = readdir DH) {
> 	$serverFileSize = -s $serverFileName;
> 	if (($serverFileName eq $filename) && ($filesize ==
> $serverFileSize)) {
> 	$numImagesReceived++;
> 	}
> 	}

Here you either compare the sizes of the temporary files to the final
files (should be the same unless the disk is full (you should check that
above) or a user is simultaniously uploading another file with the same
name) or the size of the final file before and after the upload (that
would generally not be the same so you would notice this).

You do not compare to anything on the client. If the upload was
interrupted or garbled you wouldn't notice it here (though there's a
good chance that either the web server or CGI.pm would catch the problem
and wouldn't even let you get that far.

>>What's much more interesting is whether the file
>>written out by whatever actually did the upload is the same size as the
>>file the client sent; in order to test that, you need to compare a -s on
>>that file with a size sent by the client.
>
> Yes, which is exactly what I believe I'm doing.

To believe is to not know.

>>I'm beginning to suspect the code you are running is not the same as the
>>code you are posting, since the code you are posting doesn't refer to
>>any client-submitted file sizes at all. Please only post code *you have
>>actually run*.
>
> With the exception of code that is not related to the upload itself, you
> have the exact code I'm running, above.

Now we have it (well, part of it, but we can guess at the rest). Before
this posting we had ONLY code NOT related to the upload itself. 


> I contend that the above code properly submits files selected for upload,
> ascertains the file sizes, uploads the file to $filePath, and compares the
> uploaded file sizes with the selected file sizes.
>
> I have tested this by hard-coding file names and sizes to simulate form
> submission, eliminating the upload process,

How can you test something about the upload process by eliminating the
upload process? You've eliminated the very thing you claim you are
trying to test!

> and comparing hard coded parameters with the files previously uploaded
> and stored on the server. If the file size of the uploaded files is
> different from the hard-coded values, I detect the error. It works
> albeit with the issues you originally highlighted.

The purpose of your code is trying to detect an error during upload. You
don't know that your code works until you successfully detected such an
error (and even then you know only that you can detect that specific
error).

	hp


-- 
   _  | Peter J. Holzer    | Fluch der elektronischen Textverarbeitung:
|_|_) | Sysadmin WSR       | Man feilt solange an seinen Text um, bis
| |   | hjp@hjp.at         | die Satzbestandteile des Satzes nicht mehr
__/   | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel


------------------------------

Date: Thu, 25 Apr 2013 14:29:36 -0700
From: "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>
Subject: Re: Ascertaing uploaded file size
Message-Id: <t06jn8571s70mgk9jvbcev2bn5mg930urk@4ax.com>

Peter J. Holzer wrote:

>On 2013-04-25 14:17, Joey@still_Learning.invalid <Joey@still_Learning.invalid> wrote:
>> Ben Morrow wrote:
>>
>>>
>>>Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
>>>> Ben Morrow wrote:
>>>> >Quoth "Joey@still_Learning.invalid" <Joey@still_Learning.invalid>:
>>>> >>
<snip>
>>
>> Files are selected by the user and are submitted to the server:
>
>Where are the file sizes which are submitted to the server IN YOUR CODE?

It's in my code, or it wouldn't be working! Keep reading, and you'll
discover how it's done. ;-)
>
>You haven't shown us any code which retrieves the parameters containing
>those file sizes. Instead you have shown us this:
>
>    for (my $j = 0;  $j < $imgCnt; $j++) {
>    $filename = $uploadFiles[$j];
>    $filesize = -s $filename

File names and pertinent information is contained in the [HTML5-created]
array myFile0[] which is in a form input element submitted to the perl
script.

perl: 
@uploadFiles = param('myFile0[]');
@filesize = ();
$filename = $uploadFiles[$i];
$filesize = -s $filename;
push(@filesize, $filesize);
 ...

Obviously, the filesize info could be separately submitted by using js to
ascertain file size:

files = e.dataTransfer.files;
filesize = files.size

But, there's no reason to do this, as submitted file size can be
ascertained in perl (as I have done, and shown).
>
>At this point $filesize doesn't contain a size which was possibly
>captured by some javascript code on the client and submitted to the
>server. It contains the size of the file $uploadFiles[$j] ON THE SERVER.

Which are the files submitted for upload, not the files that have been
uploaded.
>
>As far as I can see you haven't shown us how @uploadFiles is populated
>either, so we don't know what's in that array either.

Someone needs to learn HTML5 Forms.

<snip>
>>>The actual upload is being done by the webserver, or CGI.pm, or
>>>something;
>
>Um, I'd quibble with your terminology here. The server doesn't upload
>anything. It's the client which does the uploading. The server just
>receives the uploaded data (and may pass it on to a CGI script or
>something).

I agree. 
>
>> I realize nothing of the sort.
>
>I guess that's part of the problem.

Thanks for the insult, but it's nNot my problem. As far as I can tell, the
routine runs exactly as intended.
>
>> I have files on my desktop machine that are
>> being successfully uploaded and tested for size.
>
>Yes, but not in the code you've shown us. Both uploading and receiving
>the upload is happening in code you haven't shown us. 
>
Exactly the code I've shown (today).

<snipped>
>
>The purpose of your code is trying to detect an error during upload. You
>don't know that your code works until you successfully detected such an
>error (and even then you know only that you can detect that specific
>error).
>
What part of I tested the code by hard-coding errors did you not grasp? I
uploaded the files. I looked at the server folder, and by gosh, there they
are. The filesize comparisons rely on the file size values pushed into the
@filesize array BEFORE the upload. Populating @filesize with hard-coded
values in @filesize, which values are different from the file sizes on the
server works. If the file sizes in the array are different than the
filesizes of the same-named files on the server, the script detects the
error. Yes, of course, I prevent uploading and populating @filesize with
the originally submitted files.
-- 
Joey


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests. 

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V11 Issue 3933
***************************************


home help back first fref pref prev next nref lref last post