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.
Related
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...
I need to limit the number of times a pdf is downloaded by people (to 500). Ideally it would count the clicks to 500 and then remove the link. It has just occurred to me that I will also need to stop each person clicking more than once. Basically I have been asked to allow the first 500 people download a file and then end it. PHP or javascript would be prefered (its on a wordpress site)
regards
Rich
You don't wanna limit the number of times a link can be clicked, you want to limit the number of times that particular link returns a PDF file.
In other words, your link shouldn't point directly to the requested resource (the PDF), but to a PHP file that can assert that the file hasn't been downloaded more than 500 times.
Here's an example of how to output files outside your www directory to the browser.
Link to a PHP script that will control the access and serve the PDF if allowed (example with readfile(). Use the $_SESSION to manage how many times a single user has downloaded - update a value after downloading.
Use a database table or other data source to count the total downloads so that when it reaches 500, you can deny all access to the PDF.
To expand on Sherlock's solution, you want to hide your PDF behind a PHP file. When I say hide, I mean placing it in a place that is not accessible directly: consider moving it out of your "www root" or using a .htaccess to prevent accessing the file directly. Most advanced users will figure out how to access your PDF if the document is guessable and publicly available.
Your PHP should simply do the following:
Check if the document has been downloaded less than 500 times OR the user's IP has "unlocked access" to the document (you might want to allow a "window" during which a user can download again the document - some people will open the file when they actually want to save it, and don't know how to save to disk from their reader) - otherwise display an error
Store the IP address of the user for this document
Send the appropriate header for the file type: header('Content-type: application/pdf');
Send the file name: header('Content-Disposition: attachment; filename="the document.pdf"');
Send the file content: readfile($pathToPDF);
Chrome allows users to hit Ctrl + P and choose 'Save to PDF'.
Is it possible to have this function through an html button?
I want the user to just hit a button and go directly to the Save as PDF prompt ( where the file name is set by PHP and not automatically by Chrome ). So the user basically just hits the button and clicks on Save on the prompt window.
Is this possible?
Can I skip the previous steps?
Nope, it's not possible.
But, you can give the user the choice to download a HTML file output as a PDF file. There are a few libraries around, Prince is the best but expensive, so check out DOMPDF.
By the time your user can hit ctrl+P in the browse, the PHP process that generated the page (on server) is already closed.
Besides the fact that PHP exerts no direct control over browsers. It just sends them information in the form of HTML/CSS and important in this case JavaScript.
With JavaScript you could trigger the normal print behaviour of the browser but you would have no control over it.
Another approach could be to generate the PDF on server and send it as a file to the browser. In which case the browser will either ask the user if he wants to open it or it will ask the user if he wants to download it.
I've personally used fPDF to customise the PDF invoices of various open source e-commerce software. Like for example PrestaShop.
All you really need to do is download the library from (fPDF](http://www.fpdf.org/), but seeing it in action and being able to change/adapt a working version might help you so you could look for the PDF invoice in a fresh the PrestaShop install inside the folder classes the file name is PDF.php .
I lost several hours trying to make conversion to pdf on the server with no luck because my view contains some jquery functions that do the main rendering. I thought of providing a button to save as pdf using the browser but then opted to using javascript on the client side to do the rendering to pdf. This may not be the optimal solution in certain cases but looked the most sensible one in my case.
there are many libraries I just started using html2pdf.js and it is working fine so far.
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.
All,
I have a PHP5 application written with Zend Framework and MVC style. My application allows multiple users to login and see content based on their privileges. I have a dropdown on the home page. Upon selecting the dropdown, an ajax call occurs which populates the page with a table. Also, it generates a PDF file with the table data using mpdf library. There is a link called "Download PDF" in the page to allow the user to download the generated pdf.
My question is, in such environment, how to best serve pdfs to multiple users? Should I serve a single pdf with the a common name or should I create multple pdfs based on the dropdown value (looks like an overkill)? I don't want to let the users see each other's pdfs. Also, where should I store the pdfs as pretty much the entire application directory will have only 750 acccess.
Thanks,
User clicks "downlod PDF"
Parameters like ID are sent with ajax
Is there a cached version of the PDF with that ID saved? Ok, show it to the user; else:
Generate PDF
Cache it
Show PDF to user
I would have a cache key like userid-documentid (user1-document1 for example) and name the document something that would make them recognize it in a "downloads folder": your-app document-name date.pdf (ABC Half year report 2010-07.pdf for example).
I would store the cache in a /tmp directory somewhere, and present the cached data with a custom header; the following is from Example 1 # php.net:
<?php
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="ABC Half year report 2010-07.pdf"');
readfile('/tmp/user1-document1');