Link to home
Start Free TrialLog in
Avatar of mph23
mph23Flag for United States of America

asked on

Perl only will not process all items in loop.

I am trying to loop thru a text file to get selected filenames, then download these files one at a time. I don't have archive::zip on the host (godaddy won't let me install it) so I have to do it one by one (unless someone has a better solution).

This code will download the first file, but not any after that.
The log in downloadfile.log shows that it's processing 2 files; p1.tif and p2.tif.

This file is called by: downlaodsample.cgi?1107

The testdata.txt looks like:

1107      S      A      p3.tif      A-3 Plan 3
1107      S      A      p4.tif      A-4 Plan 4
1107      P      L      p1.tif      L-1 Plan 1
1107      P      L      p2.tif      L-1 Plan 2
#!/usr/bin/perl
#BEGIN {
#open (STDERR, ">../public_html/error.txt");
#}
 
use CGI ':standard';
use CGI::Carp qw(fatalsToBrowser);  
 
#--------------------------------------------------
# retrieve itemno
#--------------------------------------------------
 
$itemno = $ENV{'QUERY_STRING'};
 
$terminator = $itemno . "\xff";
 
#--------------------------------------------------
# open file  
#--------------------------------------------------
open (FILE, "../public_html/files/testdata.txt") || die (print "Could not open file.");
 
while (<FILE>) {
   chomp;
   ($item, $category, $subcategory, $filename, $description) = split("\t");
 
   next if ($item lt /$itemno/i);
 
   #exit loop if item is after one we are looking for
   last if ($item ge $terminator);
 
   #look for fileno (multiple matches possible)
   next if (($itemno) && ! ($item==$itemno));
 
   #matched
   if(($item == $itemno) && ($category eq "P")){
      download_file($filename,$itemno);
   }
}
 
print "Location: http://www.mydomain.com/public_html/printorderthanks.html\n\n";
 
#--------------------------------------------------
# DOWNLOAD FILES
#--------------------------------------------------
sub download_file {
my $files_location;  
my $ID;  
my @fileholder;
 
   ($cookiename, $cookievalue) = split(/=/,$ENV{HTTP_COOKIE});
 
	$files_location = "../public_html/files";
 
	$ID = $_[0];
	$fileno = $_[1];
 
	if ($ID eq '') {  
 	  	print "Content-type: text/html\n\n";  
   		print "You must specify a file to download.";  
	} else {
 
   		open(DLFILE, "<$files_location/$ID") || Error('open', 'file');  
   		@fileholder = <DLFILE>;  
   		close (DLFILE) || Error ('close', 'file');  
 
   		open (LOG, ">>../public_html/files/downloadfile.log") || Error('open', 'file');
   		print LOG scalar localtime();
   		print LOG ", $cookievalue, ";
   		print LOG "$fileno, $ID\n";
   		close (LOG);
 
   		print "Content-Type:application/x-download\n";  
   		print "Content-Disposition:attachment;filename=$ID\n\n";
   		print @fileholder
	}
   return 1;
}
 
sub Error {
   print "Content-type: text/html\n\n";
   print "The server can't $_[0] the $_[1]: $! \n";
   exit;
}

Open in new window

Avatar of mph23
mph23
Flag of United States of America image

ASKER

Sorry, I forgot to inlcude the first line.
Here's the entire code.
#!/usr/bin/perl
 
#BEGIN {
#open (STDERR, ">../public_html/error.txt");
#}
 
use CGI ':standard';
use CGI::Carp qw(fatalsToBrowser);  
 
#--------------------------------------------------
# retrieve itemno
#--------------------------------------------------
 
$itemno = $ENV{'QUERY_STRING'};
 
$terminator = $itemno . "\xff";
 
#--------------------------------------------------
# open file  
#--------------------------------------------------
open (FILE, "../public_html/files/testdata.txt") || die (print "Could not open file.");
 
while (<FILE>) {
   chomp;
   ($item, $category, $subcategory, $filename, $description) = split("\t");
 
   next if ($item lt /$itemno/i);
 
   #exit loop if item is after one we are looking for
   last if ($item ge $terminator);
 
   #look for fileno (multiple matches possible)
   next if (($itemno) && ! ($item==$itemno));
 
   #matched
   if(($item == $itemno) && ($category eq "P")){
      download_file($filename,$itemno);
   }
}
 
print "Location: http://www.mydomain.com/public_html/printorderthanks.html\n\n";
 
#--------------------------------------------------
# DOWNLOAD FILES
#--------------------------------------------------
sub download_file {
my $files_location;  
my $ID;  
my @fileholder;
 
   ($cookiename, $cookievalue) = split(/=/,$ENV{HTTP_COOKIE});
 
	$files_location = "../public_html/files";
 
	$ID = $_[0];
	$fileno = $_[1];
 
	if ($ID eq '') {  
 	  	print "Content-type: text/html\n\n";  
   		print "You must specify a file to download.";  
	} else {
 
   		open(DLFILE, "<$files_location/$ID") || Error('open', 'file');  
   		@fileholder = <DLFILE>;  
   		close (DLFILE) || Error ('close', 'file');  
 
   		open (LOG, ">>../public_html/files/downloadfile.log") || Error('open', 'file');
   		print LOG scalar localtime();
   		print LOG ", $cookievalue, ";
   		print LOG "$fileno, $ID\n";
   		close (LOG);
 
   		print "Content-Type:application/x-download\n";  
   		print "Content-Disposition:attachment;filename=$ID\n\n";
   		print @fileholder
	}
   return 1;
}
 
sub Error {
   print "Content-type: text/html\n\n";
   print "The server can't $_[0] the $_[1]: $! \n";
   exit;
}

Open in new window

I checked your code.
I tried running it with some events and adding some prints for check.
With input file you have given the function 'download_file' is called twice and not once.
I confirmed this by printing from inside that func.

So I guess two files are getting downloaded (Can you check if the file names getting downloaded are same? This will overwrite each other)

Also 4 files are not getting processed because you code checks for $category eq "P"
So only files with P will be processed, and in the text we have only 2 lines having P
Avatar of mph23

ASKER

You are correct, only 2 rows with a P are being processed and the sub download_file is being called twice.

As I mentioned, the log file 'downloadfile.log' shows that it's processing 2 files; p1.tif and p2.tif.

However, I only see one file p1.tif actually being downloaded. So that's the mystery.

Is it a timing issue because maybe it's trying to download p2.tif but p1.tif is still being downloaded?
Not sure what the problem is.

Any ideas?

Thanks!
ASKER CERTIFIED SOLUTION
Avatar of ozo
ozo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mph23

ASKER

The p1.tif file is being downloaded.

Are you asking if I see 2 images in that one p1.tif file?
See, I am very sure about the code you have posted above.
It is running properly and is also confirmed by your logs.

So other issue that may be there is:
- Second file is overwriting the first one.
- Or contents of both the files are getting downloaded in single file, check its contents.
- Both downloads are not able to run at same time.
 
Avatar of mph23

ASKER

Yes, I agree with everything you've said.

1. Second is not overwriting the first because I get this download file dialog box and it says p1.tif. I never see that box appear for p2.tif.
2. p1.tif is processed before p2.tif so second file (p2.tif) is not overwriting the first file (p1.tif). I have p1.tif but not file p2.tif as a download.
3. I checked the p1.tif file being downloaded and it's only 1 page.

Maybe both downloads are not allowed at the same time.
I wonder if there's a work around.

Any ideas?
Avatar of Adam314
Adam314

Your web browser is making 1 request to the server, which executes your program.  Your program is only allowed to send 1 response - which contains 1 file.   You are trying to have it send 2 files.  This is the problem.  If you look at the contents of that 1 file, you will see the p1.tif file data, then the string "Content-Type:application/x-download\nContent-Disposition:attachment;filename=$ID\n\n", then the contents of p2.tif.

You can not have your script send two files when the web browser only made 1 request.
Avatar of mph23

ASKER

But the request is in a loop so doesn't it make multiple requests?
Sorry, new to this so I don't think I'm following you.

I don't see the contents of both files in the 1 p1.tif downloaded file.

How can I make the script make multiple requests?


Thanks
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mph23

ASKER

It's a tif file and EE won't let me attach that extension. I'll try to run it with another file and see.

Will get back to you.
Thanks
Avatar of mph23

ASKER

Ok, I changed it to a jpg file, ran the page and here's the file that was downloaded.

Don't know if it matters, but it'll usually be tif files that will be processed by this download.

Thanks
strings Blue860.jpg
JFIF
Content-Type:application/x-download
Content-Disposition:attachment;filename=p2.tif
EvuT
#Tuu<
Oi/GFS, writer v00.06.00P, (c) Wang Labs, Inc. 1990, 1991
@Location: http://www.# removed by modernmatt #.com/public_html/printorderthanks.html
Avatar of mph23

ASKER

Is that what you see in the downloaded file?
I can't see that. How did you get that info?

Any suggestions on how I can have both files downloaded?

Thanks
This file confirms what I mentioned previously.  You are trying to send 2 files in 1 response - which can not be done.

You might be able to use javascript to make two requests, and update your script so it sends 1 file at a time.  I think the window.open or window.location methods will be what you should use, but don't know much about javascript.  You could post a question in the javascript zone for more help if that is what you want.
Avatar of mph23

ASKER

But how do you see that data that ozo listed?

Thanks!
I used the unix program `strings`
If you don't have that, you can use this perl command:

perl -lne "print for  /([ -~]*\w{4}[ -~]*)/g" Blue860.jpg

You might also check the length of the file compared to the length of the two original files
Avatar of mph23

ASKER

Thanks for explaining!

Avatar of mph23

ASKER

ozo and adam314: Thanks for all your help and patience.
Avatar of mph23

ASKER

How can I have part of ozo's comments removed that contains a url that I don't want published along with this question?

Expert Comment ID: 24273176

You should post to customer service
You may also want to remove the Blue860.jpg download, which contains the same url.
Avatar of mph23

ASKER

How do I remove the jpg?

Post to customer service.  Only they can remove the comments and the jpg.
Avatar of mph23

ASKER

Thanks
Avatar of mph23

ASKER

Thanks!