Reputation:
When I offer a download to a user, I don't want them to be able to copy the URL and share it with others. To go even further: I would like to give out the download only once. If they access the URL a second time, I'd like to throw a 404.
How can I prevent a user from accessing the download URL a second time and is this method full proof.
I currently serve my file as follows:
header("Content-type: application/pdf");
// Set the name of the downloaded file here:
header("Content-Disposition: attachment;filename='example.pdf'");
// Get the contents of the original file:
echo file_get_contents('example.pdf');
I've also added a table to my mysql database
+----+------+-------+------+
| downloads |
+----+------+-------+------+
| id | file | token | flag |
+----+------+-------+------+
Upvotes: 2
Views: 722
Reputation: 3225
Simply add a download counter field to your table and generate an unique URL based on the download count.
Everytime someone tries to download the file, you increase the counter in your database by +1.
The second time they open the download URL they don't get to the same URL. And you now have a download counter.
If you want to prevent the sharing of the offered URL. So the user is not downloading the file at all, you may need to create a second table where you store the user id with the file id.
Upvotes: 2
Reputation:
I think I might've found the way to do it with help of @Ben-JD 's answer. I tried to make it clear in case others stumble upon the same problem.
+----+------+-------+------+
| downloads |
+----+------+-------+------+
| id | file | token | flag |
+----+------+-------+------+
CREATE TABLE IF NOT EXISTS `downloads` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`file` varchar(255) NOT NULL,
`token` varchar(255) NOT NULL,
`flags` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
When a user clicks on the download link:
Insert the filename and token into the downloads table
$token = uniqid(); $filename = 'download.pdf';
// Do query using your favorite method // INSERT INTO downloads (file, token, flags) VALUES ('".$filename."', '".$token."', 0);
Now do the following:
Serve the file
header("Location: download.php?file=".$filename."&token=".$token);
download.php:
// SELECT filename FROM downloads WHERE filename='".$filename."' AND token='".$token."' AND flags=0;
If that query does not return a result, you can give an error. Otherwise, return the download using your code
header("Content-type: application/pdf");
header("Content-Disposition: attachment;filename='".$filename."'");
echo file_get_contents($filename);
Upvotes: 4
Reputation: 96
You would need to use a download script which redirects to the file. The script would need to verify the url via a unique token (stored in a database) before redirecting to the file. The script could record a download has been made and set a flag in the database. Check the flag to prevent future downloads.
EDIT: Here's an Example (with pseudocode):
if( isset($_GET["token"]) && !empty($_GET["token"]) )
{
//verify $_GET["token"] matches a token in the db
//verify that the download flag has not been set
header("Content-type: application/pdf");
// Set the name of the downloaded file here:
header("Content-Disposition: attachment;filename='example.pdf'");
//set the downloaded flag in the database so that this file can't be downloaded again
// Get the contents of the original file:
echo file_get_contents('example.pdf');
}
else
header("HTTP/1.0 404 Not Found");
Upvotes: 4