output a binary file to browser from perl script 
Author Message
 output a binary file to browser from perl script

Hello
I'm trying to write a script that will send a gzip'd file to the
browser via http only when the user has entered a password correctly. I
don't want a simple Location:http://etcetc tag, because I don't want
the URL to be accessible. So how do I output a 2meg gzip file - that
is, read it from the directory and spit it out to the browser?
Thanks very much
Abner

Sent via Deja.com http://www.*-*-*.com/
Before you buy.



Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script

Quote:

>I'm trying to write a script that will send a gzip'd file to the
>browser via http only when the user has entered a password correctly. I
>don't want a simple Location:http://etcetc tag, because I don't want
>the URL to be accessible. So how do I output a 2meg gzip file - that
>is, read it from the directory and spit it out to the browser?

open() it, read() it in chunks, and print the results.
--

The Internet stock bubble didn't burst on 1999-11-08.  Hurrah!
<URL:http://www.pobox.com/~kragen/bubble.html>


Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script

Quote:


>>I'm trying to write a script that will send a gzip'd file to the
>>browser via http only when the user has entered a password correctly. I
>>don't want a simple Location:http://etcetc tag, because I don't want
>>the URL to be accessible. So how do I output a 2meg gzip file - that
>>is, read it from the directory and spit it out to the browser?

>open() it, read() it in chunks, and print the results.
>--

>The Internet stock bubble didn't burst on 1999-11-08.  Hurrah!
><URL:http://www.pobox.com/~kragen/bubble.html>

Why in chunks?  I have never had any trouble sending image files in
continuous stream, so I don't see why it wouldn't work for any binaries:

if (open(FILE,"$file")) {
    binmode FILE;       # only needed for Win servers
    print <FILE>; # prints complete file
    close FILE;

Quote:
} else {

    # print error message including $! and exit

Quote:
}

--

http://www.de-srv.com/  http://cgi-help.virtualave.net/
http://thunder.prohosting.com/~cv-elgin/


Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script


...

Quote:
> if (open(FILE,"$file")) {

What is the purpose of the quotes on $file?

Quote:
>     binmode FILE;  # only needed for Win servers

                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLEASE stop saying things like that, and just show the binmode() as a
matter of course!  That is called 'writing portable Perl'.

And you forgot to 'binmode STDOUT;' also.

Quote:
>     print <FILE>;    # prints complete file

But in a very inappropriate way.  It reads the entire file into a list
of 'lines', even though there aren't any lines, then it prints the list.

      my $buf;
      print $buf while read FILE, $buf, 8192; # or whatever size

--
(Just Another Larry) Rosler
Hewlett-Packard Laboratories
http://www.hpl.hp.com/personal/Larry_Rosler/



Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script

Quote:

>>     binmode FILE;      # only needed for Win servers
>                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>PLEASE stop saying things like that, and just show the binmode() as a
>matter of course!  That is called 'writing portable Perl'.

Yes, of course.

But it is also a way of preventing whining comments like "why do I ned
it? It works on Unix without binmode()!". binmode() is a noop on both
Unix and Mac. It disables the special treatment of text files on DOS and
Win32. [I am not familiar with the platforms that weren't mentioned.]

How about:

     binmode FILE;      # noop on Unix servers

--
        Bart.



Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script

(excessive quoting now deleted.  As a regular contributor you should
know better, honestly.  The context is evidently CGI, if I'm not very
much mistaken.)

Quote:
> if (open(FILE,"$file")) {
>     binmode FILE;  # only needed for Win servers
>     print <FILE>;    # prints complete file
>     close FILE;
> } else {
>     # print error message including $! and exit
> }

We seem to be missing the appropriate CGI headers prior to sending the
data.  (Or different headers when sending the error message - I would
recommend sending an error status, as well as a content-type that's
appropriate for the error message.)

And I add my vote to the other points raised: take away the "s around
$file, and change the comment on the binmode to something like "for
portability".  And you forgot to binmode STDOUT for sending the binary
data.

--

  * Progress (n.): The process through which Usenet has evolved from
   smart people in front of dumb terminals to dumb people in front of



Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script


Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script

Recalling the previous discussion about

Quote:
> > if (open(FILE,"$file")) {
> >     binmode FILE;     #
> >     print <FILE>;       # prints complete file
> >     close FILE;

[...]

and the recent discussion about the correct way to code Perl for writing
CGI headers to non-NPH scripts, it occurred to me that the following
scenario could arise.

# suppose STDOUT is in text mode at this point

print "Content-type: application/fubar\n\n";

# Now we want to send binary; assume BINFILE was already successfully
#  opened and binmode()ed.

binmode STDOUT;
print <BINFILE>;

[...]

My question is, does binmode() take effect at the appropriate point in
the written data stream, in which case no extra precations seem to be
required; or could the binmode "overtake" still-buffered data, in which
case it would seem necessary to flush the buffers before issuing the
binmode() ?

I tried reading perldoc -f binmode, but instead of what I would consider
to be technical documentation, I'm sorry to have to say that I found
something that read like a party political broadcast on behalf of the
unix advocacy party.  Don't get me wrong: I'm a convinced user of unix
systems, and a very unconvinced user of M$ systems; but that kind of
wording is still not what I look for in technical documentation, sorry.

I also looked for perldoc -q on binmode and on flush, but am still no
wiser.

OK, the alternative approach, when we take into account that the CGI
spec told us that in non-NPH scripts the server should accept any of the
popular line-end representations, would be to binmode STDOUT from the
start, and write the CGI headers with whatever newline representation
one considered appropriate (we could take votes on \n, \012 etc).
Perhaps it's pointless pedantry on my part, but non-NPH CGI headers are
supposed to be text, and so it seemed to me to be proper hygiene to
treat them as such, and only go into binary mode for the actual binary
data.

all the best



Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script


Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script

Quote:


>>open() it, read() it in chunks, and print the results.

>Why in chunks?  I have never had any trouble sending image files in
>continuous stream, so I don't see why it wouldn't work for any binaries:

>if (open(FILE,"$file")) {
>    binmode FILE;   # only needed for Win servers
>    print <FILE>;     # prints complete file
>    close FILE;
>} else {
>    # print error message including $! and exit
>}

This won't work well if $file is 200MB and you only have 32MB of
virtual memory -- or, more reasonably, if $file is 5MB, your virtual
memory is 64MB, and you have 20 people trying to download the file at
once.

Also, it chops the data up into one-line chunks; for some data this
will be very small.  I'd use read() to read bigger chunks instead --
and then print each chunk before fetching the next one.

Also, it reads the whole file before beginning to send it, adding
unnecessary delay and probably actually reducing throughput.
--

The Internet stock bubble didn't burst on 1999-11-08.  Hurrah!
<URL:http://www.pobox.com/~kragen/bubble.html>



Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script

Quote:



> >Why in chunks?  [...]
> This won't work well if $file is 200MB and you only have 32MB of
> virtual memory -- or, more reasonably, if $file is 5MB, your virtual
> memory is 64MB, and you have 20 people trying to download the file at
> once.

right

Quote:
> Also, it chops the data up into one-line chunks; for some data this
> will be very small.

If you know that the file is small enough to fit in memory, how about
an undefined $/ ?

But in general, clearly you're right to read it in chunks of a size that
you know you can handle.

Good points.  Trust me to pick on the nits and miss the big picture.

thanks



Wed, 18 Jun 1902 08:00:00 GMT  
 output a binary file to browser from perl script


Quote:

>> Also, it chops the data up into one-line chunks; for some data this
>> will be very small.

>If you know that the file is small enough to fit in memory, how about
>an undefined $/ ?

>But in general, clearly you're right to read it in chunks of a size that
>you know you can handle.

If you know the file is small enough to fit in memory, you can simply
supply how much memory you want to use as an argument to read().  This
will be equivalent to undefining $/ for the cases when you're right,
and will still work when you're wrong.  And I don't think it's really
any more difficult: {local $/; $x = <FILE>; print $x} for one case, and
while (read FILE, $x, 131072) {print $x} for the other.

I typically undefine $/ only when reading files in chunks makes my code
more complicated -- e.g. maintaining regular expression state across
chunk boundaries.
--

The Internet stock bubble didn't burst on 1999-11-08.  Hurrah!
<URL:http://www.pobox.com/~kragen/bubble.html>



Wed, 18 Jun 1902 08:00:00 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. Outputting a binary file to the browser

2. binary file output (textual hex to binary stream - wmf image file)

3. New-2-Perl: Script output to Browser not working

4. Reading multiple files and sending output to browser with Perl

5. redirecting output from one perl script to a file (withough changing the perl script itself)

6. How to download a binary file to browser?

7. making CGI output to a file instead of a browser

8. output file to browser?

9. Reading in a file and outputting to browser

10. Output into a binary file

11. Load Binary file and then output

12. Binary File for Input/Output

 

 
Powered by phpBB® Forum Software