Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Send file to Browser

by sushi2k (Novice)
on Jul 30, 2009 at 14:44 UTC ( #784628=perlquestion: print w/ replies, xml ) Need Help??
sushi2k has asked for the wisdom of the Perl Monks concerning the following question:

Hy perlmonks,

I don't know how I can create output to a html page and also send a xls file to the browser.

Here is the scenario:

I'm creating with Spreadsheet::ExcelWriter a xls file. This file should, after creating it, be send to the browser so that it can be downloaded. But I want also some Output about the creation of the xls file (if there were any errors but also if all went well). So I got one perl-script that creates the xls and sends it to the browser. This script should also create some output in a html file.

Here is the piece of code I've found via google that sends the xls ($fileName) to the browser so that I can save it (this works, if I don't have any other output):

    ### read file and send
    my $file_size = -s qq{$fileName};

    print CGI::header({
        'content-type'        => 'application/excel',
        'content-length'      => $file_size,
        'content-disposition' => qq{attachment; filename=$fileName}
    });
    
    open my $XLS, qq{$fileName} or do {
            my $self->_generate_response({
                code        => 500,
                message     => qq{file $fileName not found: $!},
            });
            
            return;        
    };
    my $buffer;
	while(read $XLS,$buffer,16384) {
		print $buffer;
	}
    close $XLS;
If the script writes some output about the result of the creation of the xls file I get binary code after this output in my browser. And I can't download the xls file because it's written directly to the browser. This piece of code is at the begining of the script and there are no more print commands when the xls is being send to the browser:
############################################################
#html output, that shows if the creation of the xls was successful
print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Creating xls-output</title></head><body>\n";
print ($auditId." ".$auditName.");
I thougt it would be solved if I set the header to application/excel after the html-output has finished and then the xls can be downloaded again. But I still get binary code in my browser. I think it's a problem with the header, but I don't know how to solve it.
Thx in advance.

Comment on Send file to Browser
Re: Send file to Browser
by moritz (Cardinal) on Jul 30, 2009 at 15:06 UTC
    You can't output HTML and binary contents during the same request. You have to split it up into two requests, for example by displaying a HTML page that tells the user that the xls was created, and includes a link to the download location.

    That means that you have to store one of them (either xls or the status message) somewhere on disc between the requests.

Re: Send file to Browser
by psini (Deacon) on Jul 30, 2009 at 15:11 UTC

    Short answer: you can't.

    The problem is that HTTP and web browsers don't work that way. You (server) can't "send a file" to a browser, it is the browser that must request the file to you.

    This said, I see at least two options to do something that works like you expect:

    • Send a HTML page with the informations and generate server side the file. In the page, there will be a link to download the file.
    • Same thing but a bit more automagic: instead of a link on the page you can have a short javascript doing the same thing. When the page is loaded in the browser, the script will start a second HTTP request to download the xls file.

    In both approaches you have to consider two caveats: first that the file is created and saved server side, and should not be deleted until the browser downloads it, but consider also that the browser could never start the download. So you should implement some server side mechanism to delete all files older than X minutes/hours/days (depending on your context) or soon or later you'll have the server disk full.

    The second point to remember is that the files generated in this way are exposed on the internet. If the files can contain sensitive data, you should at least generate them with random names, to reduce the chance of a guess on a sequential naming scheme.

    Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

Re: Send file to Browser
by sushi2k (Novice) on Jul 31, 2009 at 10:55 UTC

    Thx for the answers. I create now a html page with all the relevant output of the xls-creation and a link to the xls that is saved on the server.

    @psini: The perl-script is only used in our intranet. It's not planned to access it via internet. But thx for the hint anyway.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (13)
As of 2014-07-22 08:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (107 votes), past polls