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

I've been looking all around the internet for the answer to this question, and all I found were some documents that only worked partially.

I'm trying to force the download of an adobe pdf file, and I don't want to reaname the ext to zip or anything like that. What I want is a link that leads to my download counter to count the download, then force the pdf file to download. I've got the file to force download, but when I try to open the file that I downloaded, adobe tells me that the file has been corrupted.

The code that I used was that from this node "Need help with downloading".

The only thing that I changed from this code was removed the

File::Type(I don't have access to this on my server)

and changed

print 'Content-Type: ', File::Type->new()->mime_type($filePath[$i]) || 'application/force-download', "\n";

to

print 'Content-Type: ', 'application/pdf' || 'application/force-download', "\n";

I'm able to download the file, but it doesn't download correctly. Can someone please tell me why, and how to go about doing this properly.

Replies are listed 'Best First'.
Re: Download PDF
by ruoso (Curate) on Jun 18, 2005 at 12:56 UTC

    You must use the proper http header to inform that the browser should download the file. It's usefull to read the protocol RFC that will contain the information you need, namely:

    BEGIN Quote:

    Content-Disposition

    The Content-Disposition response-header field has been proposed as a means for the origin server to suggest a default filename if the user requests that the content is saved to a file. This usage is derived from the definition of Content-Disposition in RFC 1806 35.

            content-disposition = "Content-Disposition" ":"
                                  disposition-type *( ";" disposition-parm )
            disposition-type = "attachment" | disp-extension-token
            disposition-parm = filename-parm | disp-extension-parm
            filename-parm = "filename" "=" quoted-string
            disp-extension-token = token
            disp-extension-parm = token "=" ( token | quoted-string )
    

    An example is

            Content-Disposition: attachment; filename="fname.ext"
    

    The receiving user agent SHOULD NOT respect any directory path information present in the filename-parm parameter, which is the only parameter believed to apply to HTTP implementations at this time. The filename SHOULD be treated as a terminal component only.

    If this header is used in a response with the application/octet- stream content-type, the implied suggestion is that the user agent should not display the response, but directly enter a `save response as...' dialog.

    daniel
      I have used this a lot with excel and pdf files:
      mod_perl example:
      $r->content_type('application/pdf'); $r->headers_out->{'Content-Disposition'} = 'attachment; filename=adobe +.pdf'; $r->send_http_header;
      Works every time!

      Don
      WHITEPAGES.COM | INC

      Edit by castaway: Closed small tag in signature

        I think that you might be on to something, but I'm not sure that I'm sure how to implement this into my script. I tried to add it to my script, but now I get a Software Error:

        Can't call method "content_type" on an undefined value at /vhdocs/rollersports/cgi-bin/dlc/ShotGun.cgi

        Any idea what would cause this error?

Re: Download PDF
by PodMaster (Abbot) on Jun 18, 2005 at 08:45 UTC
    You probably need to binmode. `perldoc -f binmode'

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Download PDF
by davidrw (Prior) on Jun 18, 2005 at 13:33 UTC
    just wanted to comment on this (which i'm sure was just overlooked cause it's not really the issue at hand):
    print 'Content-Type: ', 'application/pdf' || 'application/force-downlo +ad', "\n";
    At this point, you can just make it:
    print 'Content-Type: ', 'application/pdf', "\n";
    Since 'application/pdf' is a true value, the || will always evaluate to that value, and never look at the right hand side (RHS). The RHS was there originally because the LHS was a method call which could potentially fail, so the RHS was a backup/default. But now that the LHS is a string literal, the backup is unnecessary.

    As for the root issue, are you using the code from the parent node you referenced or from this reponse: Re: Need help with downloading ?