Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Downloading images to client PCs

by MrCromeDome (Deacon)
on Sep 12, 2002 at 14:42 UTC ( #197236=perlquestion: print w/replies, xml ) Need Help??

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

Good morning,

I post this at the risk of sounding repetitive, but I am truly baffled at this problem. I posted the original problem in this node, and have come a little ways since then, but not much. I admit I am somewhat out of my league here - I'm not terribly familiar with how HTTP headers work, which could explain most of the problem I'm having.

To recap, I have a web site which allows clients to purchase copies of selected document images online. Once the transaction has been completed, I need to send the purchased document to the client browser. Images are in multipage TIFF format with group 4 compression. I have the image being delivered to the client browser, but what the client sees when they get the image is not at all correct.

Not at all correct, I realize, is rather vague. Results vary slightly from one browser/OS to another. On Win2k with IE 5.5, the default TIFF viewer for Windows reports that the document is not of a supported format. Using WinXP with IE 6, the default image viewer will recognize the proper number of pages in the image, but only the top 1/3 or so of the first page is actually readable (the rest of the image is black). If I save (and not view) the image with either Win2k or WinXP and then use a 3rd party image viewer to bring up the image, the results are similar to viewing the image with XP's default viewer.

I'm left to believe that either there is something wrong with my content header, or something is happening to the image during delivery to the browser. To be honest though, I think it's something I'm doing ;) Here's what I got thus far:

my $file = get_image_info($document); my $filesize = -s $file; my $buffer; # Read the image file open READ, "< $file" or die "Cannot open $file for reading: $!"; binmode READ; { local $/; $buffer = <READ>; } close(READ); # For Debugging Purposes print $request->header(), " ", length($buffer), " " , -s $file ;
I'm confident that the image reading portion of that is ok. When the debugging info gets sent to the browser, what Perl reports the size on disk to be (and the size of $buffer) match what the file size on disk actually is. Once I was sure that I was reading it ok, I worked on delivering the image. I have tried the following things listed below. Check the comment above each for the result.
# This didn't work. Displays "Save As" dialog twice, no image sent. print "Content-type: image/tiff\n"; print "Content-disposition: attachment; filename=image.tif\n\n"; print $buffer; # This kinda works. Displays "Save As" dialog twice, but image is # corruppted (see description in post). print "Content-Type: image/tiff; filename=image.tif\n"; print "Content-Disposition: attachment; filename=image.tif\n"; print "Content-Length: $filesize\n\n"; print $buffer; # Same result as above. print $request->header(-type => "image/tiff", -attachment=>'image.tif'), $buffer; # This almost works. Only displays "Save As" dialog once, image is # messed up though (see description in post). print "Content-Disposition: inline; filename=image.tif\n"; print "Content-Length: $filesize\n"; print "Content-Type: image/tiff\n\n"; print $buffer; # Same result as above, just done a bit differently. Changing the con +tent # type did nothing for me. print $request->header(-Content_Disposition => "inline; filename=image +.tif", -Content_Length => $filesize, -Content_Type => "application/octet-stream", ), $buffer;
Is there something obvious (or not so obvious) that I'm missing here? I spent the better part of yesterday combing through the Monastery looking for additional insight, but I can't find something different than what I've tried (or else I'm misapplying something that I've found there).

Any help, comments, or insight are very much appreciated. Thank you!


Replies are listed 'Best First'.
Re: Downloading images to client PCs
by fglock (Vicar) on Sep 12, 2002 at 15:10 UTC

    I hope this helps:

    Try it with a JPG image first. It is more standard and you don't have to care about possible browser bugs. Go back to TIFF when you are more confident. Start with simple TIFF before going multipage.

    An attachment is supposed to go into a "multipart" message (text + graphics). Maybe that's why you are asked to "save-as" 2 times.

    If you are using a Windows server, you should binmode STDOUT.

      Excellent suggestions, both of you. I completely forgot about binmode-ing STDOUT. I also hardcoded $file to point to a JPEG sitting on the same machine - no luck though :( Same type of thing happens. Image appears on the client browser, but only about the top 1/3 or so of it.

      What next? :(


Re: Downloading images to client PCs
by guha (Priest) on Sep 12, 2002 at 15:15 UTC

    Regarding sending files to clients I have not worked with .tiff files personally, but I guess you would have to tell the client how the data is encoded.

    Perhaps something in the line of

    undef $/; # Slurp whole file into scalar, # otherwise only to first \n my $file = "ms.tif"; open(READ, $file) || die "Yada yada"; binmode(READ); my $buffer = <READ>; close(READ); binmode(STDOUT); print "Content-Type: image/tiff\n"; print "Content-Transfer-Encoding: binary\n" # Was base64 print "Content-Disposition: attachment; filename=ms.tif\n"; print "Content-Length: ", -s $file, "\n\n" #Show progress bar print $buffer;

    This is untested code and I may be barking up the wrong alley tree.

    I see that you binmode(READ) but what about STDOUT ??

    Update: Stubborn me, codeexample is now updated and tested on IE6.0

    The only annoying issue left is that the you get the Open/Save dialog twice.

    ... chromium crusted tweezers gleaming in the moonlighty night --FZ

Re: Downloading images to client PCs
by valdez (Monsignor) on Sep 12, 2002 at 15:55 UTC

    I tried your code (the first 'inline' version) on my linux box and here is what i got:

    • Netscape 4.78: shows the image as background; if I try to save the page I get the correct name for the image;
    • Netscape 7: pops up a window to save or preview the image
    • Lynx 2.8.4: saves the image with the correct name
    • Konqueror 2.2.2: does nothing :(

    I don't know if it makes a difference, but every header should be followed by \r\n.

    Ciao, Valerio

      I don't know if it makes a difference, but every header should be followed by \r\n.

      Not in Perl it shouldn't. \n and \r map to different values depending on platform. What you should have said was that "every header should be followed by \015\012". This is all documented in perldoc perlport.


Re: Downloading images to client PCs
by dws (Chancellor) on Sep 12, 2002 at 17:46 UTC
    I need to send the purchased document to the client browser ... in multipage TIFF format with group 4 compression ... but what the client sees when they get the image is not at all correct.

    Think out of the box on this one. You're selling them bits, and you need to make sure the bits arrive intact. One reliable way to do this, assuming your clients are on Win32, is to send them .zip files. (There's probably an equivalent reliable interchange format for the Mac.)

    So, pre-zip your TIFF files on the server side, and serve up .zip files. This will require that your clients have WinZip (or equivalent) installed, but this is a free download from various places. If you have clients with Macs, ask around for what a reliable download format is.

      Aladdin Systems' Stuffit Expander is pretty much the de facto decompression program on the Mac (it's come preinstalled for years). While it has its own compression format, .sit, it can also handle .zip files perfectly (as well as .tar, .gz, .smi, .uu, .lzh, and others). Zip files should pose no problem for Mac users.

      Good idea, dws.

      How do I love -d? Let me count the ways...
      I like this suggestion. . . pre-zipping the TIFFs is not terribly feasible, but it was pretty easy to whip something up to create them on the fly. Same problem though: when the zip file gets to the client, it's not usable. I was able to open the downloaded zip and look at the contents, but when I tried to view the contents, WinZip reports "Extracting building.jpg; Error: invalid compressed data to inflate." I opened the zip that was created on the fly (the one on the server) to make sure it was valid, and the file seemed ok.

      The code I used looks like this:

      my $file = 'd:\imaging\building.jpg'; my $zip_name = get_session() . ".zip"; my $zip = Archive::Zip->new(); $zip->addFile($file) or die "Can't add to zip!\n"; $zip->writeToFileNamed($zip_name); my $filesize = -s $zip_name; my $buffer; # Read the zip file open READ, "< $zip_name" or die "Cannot open $zip_name for reading: $! +"; binmode READ; { local $/; $buffer = <READ>; } close(READ); binmode STDOUT; print "Content-Disposition: inline;\n"; print "Content-Length: $filesize\n"; print "Content-Type: application/zip\n\n"; print $buffer;
      I'm serving this up with Apache 2.0.40 on WinXP.


        Same problem though: when the zip file gets to the client, it's not usable.

        Archive::Zip says this:

        Under Windows, things lock up/get damaged

        Q: I'm using Windows. When I try to use Archive::Zip, my machine locks up/makes funny sounds/displays a BSOD/corrupts data. How can I fix this?

        A: First, try the newest version of Compress::Zlib. I know of Windows-related problems prior to v1.14 of that library.

        If that doesn't get rid of the problem, fix your computer or get rid of Windows.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://197236]
Approved by Mr. Muskrat
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2021-10-25 07:00 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (89 votes). Check out past polls.