• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 295
  • Last Modified:

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

0
mph23
Asked:
mph23
  • 15
  • 5
  • 4
  • +1
2 Solutions
 
mph23Author Commented:
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

0
 
vikaskhoriaCommented:
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
0
 
mph23Author Commented:
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!
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
ozoCommented:
what do you see in the one file that is being downloaded?
0
 
mph23Author Commented:
The p1.tif file is being downloaded.

Are you asking if I see 2 images in that one p1.tif file?
0
 
vikaskhoriaCommented:
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.
 
0
 
mph23Author Commented:
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?
0
 
Adam314Commented:
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.
0
 
mph23Author Commented:
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
0
 
Adam314Commented:
Your script doesn't make requests, it makes responses.  It is the browser that makes requests.

It goes like this:
   You type in your browser (or click on a link, or form), http://www.yoursite.com/cgi-bin/somepage.pl
   Browser logs in to www.yoursite.com
   Browser asks for page /cgi-bin/somepage.pl (providing form data)
   Web server runs /cgi-bin/somepage.pl
   The somepage.pl provides a response
   The somepage.pl can only provide 1 response, because there was only 1 request


Can you attach the p1.tif file?

0
 
mph23Author Commented:
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
0
 
mph23Author Commented:
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
0
 
ozoCommented:
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
0
 
mph23Author Commented:
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
0
 
Adam314Commented:
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.
0
 
mph23Author Commented:
But how do you see that data that ozo listed?

Thanks!
0
 
ozoCommented:
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

0
 
ozoCommented:
You might also check the length of the file compared to the length of the two original files
0
 
mph23Author Commented:
Thanks for explaining!

0
 
mph23Author Commented:
ozo and adam314: Thanks for all your help and patience.
0
 
mph23Author Commented:
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

0
 
ozoCommented:
You should post to customer service
You may also want to remove the Blue860.jpg download, which contains the same url.
0
 
mph23Author Commented:
How do I remove the jpg?

0
 
Adam314Commented:
Post to customer service.  Only they can remove the comments and the jpg.
0
 
mph23Author Commented:
Thanks
0
 
mph23Author Commented:
Thanks!
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 15
  • 5
  • 4
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now