Download an Excel File in response to submitting a form - php

I want to allow a user to enter a date range and then be able to download an Excel file with data retrieved based on that date range.
Initially I had this working by submitting the form as a GET request for the same page. If the GET params are present the page will retrieve the data and output the needed headers and then the data. I would then exit; from the process to prevent the page from loading (since I had to send the headers with the Excel data).
This works. However I want to include a progress indicator that will go away once the data has been sent. However I cannot find a way to do this.
I can start such an indicator when the form submit button is pressed, but I cannot find a way to turn it off once the document had been output for download.
Ajax does not work in this sort of situation, btw.
Can anyone suggest how to do this? I've seen suggestion here on SO about loading the output into a hidden iframe but I do not understand how to do this myself.

Because I have no code on which I could base I will write you the theory mostly.
user requests to download a file
you load a page where inside you are creating the file, the process takes some time, during which you show the user a progress bar.
instead of throwing this file to the user with header function (which you cannot use as you already are printing on the screen) you save the file into a temp directory. preferably call it with a random name, or a timestamp.
by the end of file creation print on the screen a JavaScript command like this:
<script language=”JavaScript”>
self.location=”download.php?file=whatever_you_called_it.xls”;
</script>
set the header for the Excel download with something like this:
header('Content-disposition: attachment; filename=your_excel_file.xls');
header('Content-type: application/xls');
readfile('tmp_dir/whatever_you_called_it.xls');
unlink ('tmp_dir/whatever_you_called_it.xls');
its always good to clean the things after yourself. be aware that it is possible that something does not get deleted. So preferably you would have a garbage collector anyways. And keep files out of public directories
Obviously, if the data is not sensitive, then you can simply set javascript directly to the file and the browser will download it directly. But then you would need some kind of garbage collector to clean all these files that are created... it would be messy...

Related

Codeigniter - How can I initiate the download of a file and reset the form to be used again

Using Codeigniter, I'm trying to do something basic.
The site has a form where users upload files for processing. After the files are processed, new files are created and saved in a zip file. Then I use $this->zip->download() to start the download.
But after that I can't do anything to refresh the upload form. And if I reload the view first, the download doesn't work.
All I want to do is upload the files, create the zip, download the zip and wind up with a clean upload form.
Any suggestions how to approach this?
I don't think you will be able to do it on the same page because of missmatched headers. You could try the following: when the zip is ready save it and name it some random/unique id/md5 anything and print the download link in the view with "click here to download your file" with target="_blank" param so it opens in a new tab. (usually browsers are smart enough that it will auto close it when you accept the file). And so you can reset the form in the view as well.
Another way could be with ajax and js i guess but that would be much longer to write.
Ps.: just dont forget to delete the files after x amount of time (if you dont need them)

how to open a PDF with an ajax call

I have a PHP script that downloads a PDF file from the server and prompts you to either open it, or save it. The script accepts a one time token, which is used in place of a file name, to hide the file name.
If you go to the actual php page, http://example.com/files/download/token the script works fine and it downloads the PDF.
I could just send people to that page with a standard link tag, but once the file downloads I need to update content on that page which is returned through that download script.
Is there any way to have ajax call open up a new window where the file will download and then return the data that I need to update the current page?
There is more to the download script, but the main piece is the actual downloading part:
header("Content-type: application/pdf");
$this->load->helper('file');
readfile("static/temp_statements/".$local_file_name);
unlink("static/temp_statements/".$local_file_name);
One trick that I have used in the past that might be useful to you is
Supply a query param in your ajax call to download the PDF. This will be a unique name.
The server process that streams the PDF for download sets a cookie with this unique name.
You poll in your page waiting for this cookie to appear.
When the cookie appears you can assume the file has downloaded, and you can do your contingent action.
And you do not need to open a window to make this happen. You could just append an invisible iframe like this:
$(some selector).append($("<iframe width='1' height='1' frameborder='0' src='" + url + "'></iframe>"));
In the interests of honesty and transparency, I originally found this idea from this SO answer and it worked for me: Detect when browser receives file download

PHP send data to parent window without using javascript

I am using FPDF to create a pdf document in an iFrame... During the pdf creation the script communicates and gets a lot of data from the server, and then I would like to display a progress bar.. That is why I have put the php generator in an iFrame.. then my plan was that the php script could send the looped data to the parent window..
e.g. every time a loop is made it says $count++;, then I know how many loops it has gone through, and I already know that it is going to limit the rows to the first 200 rows.. Then I would like to display the looped data in the parent widow like so: $count of §goal has been generated successfully!.. At the moment I am using jQuery, where I ask the php to echo some jQuery script every time a loop is made to display the results like so window.parent.count($count, $goal);.. Count in the parent winodw and it actually works well until the PDF has to be shown.. then I get an error message that tells me that the script is unable to display the PDF because the page already has outputted data..
Does anybody know how to make the PHP to send the data to the parent window, so I prevet the using of echo?
Sorry for my bad english.. if wished I can try to upload my script later for you to see...
I do it a bit differently...
I also wrote an application in which the PDF generator needs to fetch a rather large amount of data, so the generation takes a few seconds.
I use jQuery to fetch a php-page in the background. During this download, the screen turns gray and displays a classic "please wait"-circle. The only output that the php-file generates is an "OK" echo, together with a file link, when the generation has been completed. Instead of displaying the file inline, I save the PDF in a folder ($pdf->Output('filename.pdf','S')) and offer it as a download using the provided link and the jQuery-callback.
I hope you understand what I mean. Maybe this thought will help you a bit further.
EDIT: Don't know if this will work, but I just thought of it...
You could save the file and output the filename. Using jQuery, you could then refresh the contents of the iframe to fetch a page in which you display the already saved PDF inline...

How to write to database in Symfony2, when a link is clicked on the website?

In a project I'm working on, the client has required that every time a user clicks on a link to download (they will be downloading a video or mp3), there should be a log kept of who has downloaded what and when.
I have a table in my database set up to record the User ID, the File ID, and the date when it was downloaded. However, I don't know how to do this, as the link is basically an tag (obviously).
What is the best way to achieve this?
Probably the simplest solution would be to write simple onclick ajax event.
If you want noscript solution you'll have to create some download wrapper, that'd serve you proper file. Just create special route and controller (eg. /downloads/filename), increment download meter for this one and return asset instead of html response. Don't forget to set proper Content-Type header tho.
There's also IgorwFileServeBundle that could help you loads.
Instead of linking to the MP3 file, you'll have to funnel the download through a PHP script that writes to the database and then sends the MP3 data with with the right headers. For maximum performance use the "X-Sendfile" header instead of the PHP readfile function.
Alternatively you could set up a cron job for a Symfony console command line tool that parses the Apache access log and writes to the DB whenever it encounters an MP3 file.

Make Generated Word Doc Editable to User

My php script changes the headers to match a word document which the user will download, however, when the user downloads it, it is make read-only. I know the user can manually modify this but I want it to be done from my script itself.
My current headers are:
header("Content-type: application/vnd.ms-word");
header("Content-Disposition: attachment;Filename=License2011.doc");
The document will be downloaded by the browser into a temporary location. It is made read-only on purpose to avoid the impression that the user can edit the document, and upload the changes automatically by clicking "Save" (which is the intuitive assumption of everyone not familiar with how HTTP works, and frequently leads to problems when half a day's work they did on a temporary document vanishes forever).
I don't think you can change that "read only" bit on your end. It's up to the browser.
There is, sadly, currently no standards-compliant way to allow a user to download a document, open it in their software, save it, and automatically re-upload it.

Categories