Limiting the number of times a link is clicked - php

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);

Related

Secure files and display them as well

My question is about HTML and PHP.
This is my setup right now:
A website where user have accounts
A FTP server with pictures (currently none)
Files are currently saved on the website in the "PICTURES" folder (which is accessible by everybody who know the full URL)
So, I would like to know how I can display the images without storing them on the website (which will fix my URL problem).
My idea was to move the files on the FTP server, and when a users logon and request a page with those images, download them through a FTP connection, save them on the website, display the images, and remove them. Which would make them accessible only between the downloading time. But this solutions sounds REALLY bad to me.
You need always to have a place where your images are stored. But, if you don't want to give a user the chance to know where are stored, you can create a system which is used to show the images.
Think about this, if you want to download a file from Mega, you can't access to the URL where the file is stored, instead of that, the server itselfs calls a system who assign you a "key" and you can download the file only through that system using your "key".
You could use a system like "base64" so you can encode your image, and show it using it, or, you can use the "header" modifier so, you can display an image using a PHP code.
For example your image tag will be like:
<img src="processImage.php?id=01&user=10&key=123" />
So, your processImage will return a "tricky" image, actually not the image, but the code processed by PHP will be returned, like using "imagejpg()" function with the header "Content-Type:image/jpeg" and then the user will not know where the image is stored actually but the img will works actually.

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

How to rename the original file before sending it to user

Actually I have some download link on my website something like "http://www.example.com/somesong.mp3". Now when user click on this link they get somesong.mp3 but I want to change it before they download. I found many scripts that made it possible but didn't get exact right script. Because I want that when the user clicks on download link the file downloading should be started just after the click with the new file name as I want to use.
But in all the scripts which I downloaded, first the php processing starts for a few minute (I think it depends on the file size) and then rename it. Is there a way to direct force the file in header with new file name.
Thanks.
try this
header("Content-Disposition: attachment; filename=whatever you want");

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