Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Force Download to a .xls file

by Andre_br (Pilgrim)
on Jan 04, 2005 at 00:15 UTC ( [id://419108]=perlquestion: print w/replies, xml ) Need Help??

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

Hello everybody,

I´m stuck in a task I won´t acomplish without thy help.
Its so simple and tricky that irritates! I just want the client´s browser not to go on loading a .xls file. Instead, I want him to show the upload dialog and ask for the file name, the directory etc...

Here´s my code:
my xlsfile = "table.xls";
open(DLFILE, "../uploads/$xlsfile") || die "Error";
@fileholder = <DLFILE>;
close (DLFILE);
print "Content-Type: application/x-download\n";
print "Content-Disposition: attachment; filename=../uploads/$xlsfile\n\n";
print @fileholder;

The result of the code above is that he does show the dialog box, but he displays instead of the name of the file, the name of my CGI script. And also, and worse, the file it saves is almost empty and misformatted.

Any ideas?

Thanks a lot, guys!

André

Replies are listed 'Best First'.
Re: Force Download to a .xls file
by jmcnamara (Monsignor) on Jan 04, 2005 at 01:33 UTC

    Try the following Content-type and see if it gives better results.

    If the program is running on Windows then make sure to binmode the file streams. This may be what is causing the file corruption.

    #!/usr/bin/perl -w use strict; my $filename ="../somepath/test.xls"; print "Content-type: application/vnd.ms-excel\n"; print "Content-Disposition: attachment; filename=$filename\n"; print "\n"; open TMP, $filename or die "Error message here: $!\n"; binmode TMP; binmode STDOUT; print <TMP>;

    --
    John.

      Hey John!

      It's a great honour to talk to you. Your Spreadsheet::WriteExcel is just unbelievable. It is being of huge help with the site I´m working on right now - this one is for me, not for a client. You´ve done a great job, congratulations!

      In fact, your binmode tip was precise. It´s working just fine now. Thanks!

      The only thing that´s not too beautifull for the user is that when the dialog box appears, it shows: "Downloading the file: export.cgi?action=3. Do you wish to open it or save it?". Is there any way to skip that dialog and go straight to the window 'Save as'? Any hacks to do it?

      In fact, the browser is correct; but he´s showing the secret of the magic...lghs

      Take care, John!

      André

        >> Is there any way to skip that dialog and go straight to the window 'Save as'? Any hacks to do it?

        honestly, would you want your browser to save files unasked?
        for the naming issue, you could return a redirection header to the excel-file instead of printing the files contents. that way the name would be displayed correctly.
Re: Force Download to a .xls file
by Errto (Vicar) on Jan 04, 2005 at 01:45 UTC

    I assume by my xlsfile = "table.xls"; you really mean my $xlsfile = "table.xls";. In that case it ought to work. Also, unless your server-side xls file is really a text file of some kind, you should not read it using @fileholder = <DLFILE>; because that will split it on newlines, which could do funny things if it's a binary file.

    Update: The correct code for that is

    local $/; binmode DLFILE; my $fileholder = <DLFILE>;
    Putting the data in a scalar instead of an array so it's not split in arbitrary places.

Re: Force Download to a .xls file
by edan (Curate) on Jan 04, 2005 at 12:15 UTC

    I use the following incantation, with success:

    print $cgi->header( '-type' => "application/octet-stream; name=$file", '-Content-Disposition' => "attachment; filename=$file", '-Content-Transfer-Encoding' => "binary");

    Note that $file is the basename, with no path - maybe that's all that's messing you up. In your case, it should just be "$xlsfile" I think.

    --
    edan

      Just as a little side not to all this, i've finally managed to get it to work using this notation.

      print "Content-type: application/vnd.ms-excel\n"; print "Content-Disposition: attachment; filename=$filename\n"; print "\n"; open TMP, "$directory/$filename" or die "Error message here: $!\n"; binmode TMP; binmode STDOUT; print <TMP>;

      Please note that the first bit just uses the basename of the file, so without the whole directory path. Whereas the second bit uses the $directory path so it's absolute on the file system. This little thing had me stumped for a while there, so thought i'd share incase others have the same problem.

      Best of luck,
      Tom

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2024-04-24 01:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found