Protecting multiple downloads using unique URLs

A little over a year ago, I wrote a post about a PHP script I had created for protecting a download using a unique URL. The post turned out to be pretty popular, and many of the comments included requests to extend the script in useful ways. So, I’ve finally gotten around to updating the script to generate multiple URLs (up to 20) at a time, to allow different files to be associated with different keys, and to allow brief notes to be attached to the download key.

I’ve also added a simple page that prints out a list of all of the keys generated the date and time that each key was created, the filename of the download on the server that the key accesses, the number of times the key was used, and any attached note. This should make it easier to generate gobs of keys, drop them into an Excel spreadsheet, and help the files’ owner keep track of who’s getting which file, and how often.

The scripts themselves are a little more involved this time around, but the general idea is the same. A unique key is generated and combined with a URL that allows access to a single file on the server. Share the URL/key instead of the URL to the file itself to allow a visitor to download the file, but not to know the location of the file. The key will be valid for a certain length of time and number of downloads, and will stop working once the first limiting condition is met. This should prevent unauthorized downloading due to people sharing the keys.

How it works

There are six main components to this system:

  1. the MySQL database that holds each key, the key creation date and time, the maximum age of the key, the number of times the key has been used, the maximum times the key may be used, the file associated with the key, and the note attached to the key, if any
  2. a generatekey.php page that generates the keys and outputs the corresponding unique URLs
  3. a download.php page that accepts the key, checks its validity, and either initiates the download or rejects the key as invalid
  4. a report.php page that returns all of the data in the database
  5. a config.php file that contains variables such as number of downloads allowed, the maximum allowable age of the key, and the filenames of the downloads, along with the database connection information
  6. the .zip file(s) to be protected

The files

The files, along with two example downloads, are available for download as a .zip file.

Download the protecting multiple downloads PHP script

The MySQL database

Using whatever method you’re comfortable with, create a new MySQL database named “download” and add the following table:

CREATE TABLE `downloadkeys` (
  `uniqueid` varchar(12) NOT NULL default '',
  `timestamp` INT UNSIGNED,
  `lifetime` INT UNSIGNED,
  `maxdownloads` SMALLINT UNSIGNED, 
  `downloads` SMALLINT UNSIGNED default '0',
  `filename` varchar(60) NOT NULL default '',
  `note` varchar(255) NOT NULL default '',
  PRIMARY KEY (uniqueid)
);

How to use the scripts

The scripts require a little setup before they’re ready to be used, so open config.php in your text editor of choice.

Change the values for $db_host, $db_username, $db_password, $db_name to point to your database.

Set the variable $maxdownloads equal to the maximum number of downloads (actually, the number of page loads).

Set the variable $lifetime equal to the keys’ viable duration in seconds (86400 seconds = 24 hours).

Set the variable $realfilenames to the real names of actual download files on the server as a comma-separated list (this is optional; you can also use a single filename or just leave it as empty double-quotes: “”). If you have more than one file to protect, enter the names as a comma-separated list and the script will create a drop-down menu as the Filename field. If you leave the variable blank, the form will display an empty input box as the Filename field.

Set the variable $fakefilename to anything – this is what the visitor’s file will be named when the download is initiated.

I would strongly recommend renaming generatekey.php, as anyone who can view it will be able to create unlimited numbers of keys, and worse, they’ll be able to see the filenames (if you set them in config.php). I would also recommend that the directory you put these files into, and each directory on your site (/images, /css, /js, etc.), contain an index.html file. This is a simple security measure that will prevent visitors from snooping around a directory and viewing its contents (though access to the directory contents is usually prohibited by a setting on the server).

Place all the PHP scripts and your .zip file(s) into the same directory on your server.

That’s all there is to it. Whenever you want to give someone access to the download, visit the generatekey.php page and fill out the form. It will generate a key code, save it to a database, and print out a unique link that you can copy and paste into an email or whatever. The page that the unique link points to checks to see if the key code is legitimate, then checks to see if the code is less than X hours old, then checks to see if it has been used less than X times. The visitor will get a descriptive message for the first unmet condition and the script will terminate. If all three conditions are met, the download starts automatically.

Errors and issues

Note: The download will not initiate automatically, and will actually be output as text on the page, if the download.php page is changed to send headers or any output to the browser. Be careful when making modifications or incorporating this script into another page.

Check the HTTP headers (Google for an online service that does this, or install the LiveHTTPHeaders Firefox plugin) of the download link. If the script is working correctly, you should see Content-Transfer-Encoding: binary and Content-Type: application/octet-stream in the headers. If you’re getting a page of text instead of the zip file, you’ll probably see Content-Type: text/html.

Example HTTP headers for a correctly working download

If the script is working correctly, the HTTP headers will look something like this:

HTTP/1.1 200 OK
Date: Sun, 20 Jun 2010 13:31:50 GMT
Server: Apache
Cache-Control: must-revalidate, post-check=0, pre-check=0, private
Content-Disposition: attachment; filename="bogus_download_name.zip"
Content-Transfer-Encoding: binary
Pragma: public
Content-Length: 132
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: application/octet-stream

65 thoughts on “Protecting multiple downloads using unique URLs

  1. Vinyl Candy

    This is great! ONE THING: I have 5 parts (or 5 different zip files) I want to generate (1 single) download key that will start the download process for all 5 zips.
    a. Is that possible?
    b. If not than generating 5 different download codes based on 5 different zips. they will all have to same “save-as” file name.

  2. Vinyl Candy

    Also: There seems to be a LIMIT to the file size of MAX 33554432 bytes
    Fatal error: Allowed memory size of 33554432 bytes exhausted”
    How can I bump this limit up to and beyond 130MB?

  3. jonathan

    Not working for me ! always sending me a 0byte file except if i change the value of $file
    error log :

    [08-Jul-2009 17:04:41] PHP Warning: filesize() [function.filesize]: stat failed for download.zip in /home/commint/public_html/dl/download.php on line 43
    [08-Jul-2009 17:04:41] PHP Warning: readfile() [function.readfile]: Filename cannot be empty in /home/commint/public_html/dl/download.php on line 48

  4. Ian

    Hello ardamis,

    I can’t tell you how much this script is appreciated, thank you!

    I have run into a slight problem, however. If you have a moment, I do hope you’ll be able to help.

    I am able to reach the generator page. Once I click ‘Generate Key’, I am brought to a new page that shows an error in addition to the ‘x keys successfully created’. There is no download link displayed.

    The error reads as follows:


    http://xxxxx.com/xxxx/xxxxxx/download.php?id=26928bcefb67d878dbe9f2f2421f20274a5f3189c7e40

    Warning: mysql_real_escape_string() expects parameter 2 to be resource, null given in /home/content/i/n/d/indecisiveian1/html/blog/somethingnew/downloadkey.php on line 84

    Warning: mysql_real_escape_string() expects parameter 2 to be resource, null given in /home/content/i/n/d/indecisiveian1/html/blog/somethingnew/downloadkey.php on line 85

    Any ideas?

    1. Ian

      Hello again ardamis,

      Thanks for the quick reply.

      I tested out my connection info with the testing script your provided and indeed, my information is correct. I was able to successfully connect to my DB, so my dbconnect.php does contain the correct information. That being said, the generator does work, in terms of producing keys (I currently have some 6 or more according to the report). However, there is no download link created.

      Any other ideas about what it could be?

      1. Ian

        Ok, sorry if this is a double post.

        I spoke to a friend and he noticed I was missing the $link infront of the mysql_connect statement (D’oh!). So, the errors are gone now (hooray!).

        However, when visiting the generated link, the download does not begin. Instead, I view a blank screen.

        Do you know why this could be?

  5. ardamis Post author

    I’m glad to help. Try uncommenting line 33 in download.php , changing:
    // Debug echo "Key validated.";
    to
    echo "Key validated.";
    and let’s see if that text echos when you use a newly generated key.

    1. Ian

      Hi again ardamis,

      I have uncommented line 33, as you have suggested. Now, upon visiting the generated link, “Key validated.” appears on the screen (as expected?). The download, however, does not begin.

  6. ardamis Post author

    Ok, well, that helps narrow it down. It could be the part of the script that initiates the download, or maybe the download file is missing, or perhaps your browser is blocking this file transmission. Can you tell me what OS/browser/version you are using?

    I’ll be able to test this more thoroughly tomorrow.

    1. Ian

      Thanks again for keeping at this with me.

      Vista Home Premium.

      I’ve tried the generated links in both IE v.8.0.6 and Chrome v.2.0.172.37. Neither browser brings up a download prompt when visiting the link.

      For information’s sake, all the files are uploaded in a single directory; they are not separated (was hoping to have it working before rearranging for security).

      Also, should I be referencing the file by name only (e.g. actual_file.zip) or by path (/xxxx/actual_file.zip) in the config file?

      Have a good night!

  7. ardamis Post author

    Crap. I changed a variable name throughout the script, but missed one instance. Even when it the script would initiate the download, you’d only get a 0KB file, as Jonathan pointed out some time ago. I’ve uploaded the fixed script. Please download it again from this page.

    If your download file is in the same directory as download.php, you don’t need to include the /path/to/folder/ as part of the $realfilename variable in config.php. I haven’t tried putting these things in different folders yet, so I don’t know that including the path will work.

    Let me know what happens.

    1. Ian

      Afternoon!

      I’ve re-downloaded the files and upped them on my server. Now, when visiting the generated link, a page full of various characters appears (still no download prompt).

      I tested the generated link in both IE and Chrome and received the same results (page full of various characters).

      Also, thanks for the path info!

  8. Andrew Devenish-Meares

    Hi,

    Just a quick note to say thanks for this code. It did exactly what I needed and saved me a bunch of time.

  9. Tom

    Thank you Ardamis for wonderful script!

    Would it be possible to add input fields for $realfilename and $fakefilename in to the downloadkey.php so that it would be easier to create download keys for multiple files?

    Also where could I change the location for the downloadable file so that I could locate the file outside of the www (in the server root)?

  10. lascaux21

    I’ve also had an issue with large file sized ZIP files ending too soon. I’ve managed to get around the problem by replacing the “readfile” with a header(“Location”), but this isn’t optimum. Anyone figured out a way to solve this? My research indicates it may have something to do with “chunked transfer encoding”, and someone suggested using blobs to calculate size. Over my head, unfortunately…

  11. Chad

    I downloaded and installed this with no problem. It works great but only for 1 file. Whatever file I have set as the default file ($realfilename) will always download fine. if i have multiple files in the same directory, and enter a different file name in the “downloadkey.php” form, the default file still downloads. How can I use this and choose which file to generate the download key for? Please help…I love this!!

  12. ardamis Post author

    OK, I’ve updated the script to fix the issue Chad reported. I’ve also reduced the size of the keys to 12 characters, and made some changes to the database.

    It’s now possible to add a list of download files to the $realfilenames variable in config.php, so that the form generates a <select> menu of all the files (instead of making you type the name in to an <input> field each time).

    I’ve also added a number of comments to download.php to better explain step-by-step the process by which each key is validated.

  13. Ruark

    ardamis, what a great piece of code 🙂

    My 1st question is regarding the real file URL. I would like to structure where the files are kept. I dont really like leaving all files in one folder (security and ease of keeping it neat)

    Is there anyway to do this? the dropdown should be able to show directory structure should it not?

    My 2nd question is regarding the keylimit. Why is it limited to 20? is this a code limit or a hash generation limit? If I want to use this to send multiple (say 50) people unique links to the same file, would I need to increase the hash character amount?

    thanks again for your reply and this great piece of php

  14. Tom

    Ardamis – I love this script.
    Would it be possible to update the download counter after successful download?
    Now the download counter is always updated even when download is canceled before it is finished or when the download is somehow not finished successfully.

  15. Meg

    Hey, this script is awesome. But I have a question: How do I go about removing the option that creates the $fakefilename? I just want it to be the original one.

    I have a 100 or some files I want to send to a friend using this and they all will appear with the same name except the ( (1), (2) copy tags) behind them. I want all to have a unique name.

    So I tried to delete this line: header(‘Content-Disposition: attachment; filename=”‘.$fakefilename.'”‘);

    But it only gave me the download.php instead of the zip file. What do I have to modify to make this work?

    Thanks, Meg

  16. Meg

    By the way, also this line in config.php

    // Set the name of local download file – this is what the visitor’s file will actually be called when he/she saves it
    $fakefilename = “bogus_download_name.zip”;

  17. Meg

    Nevermind. I think I found a solution. I just change the line:

    header(‘Content-Disposition: attachment; filename=”‘.$fakefilename.’”‘);
    to
    header(‘Content-Disposition: attachment; filename=”‘.$realfilename.’”‘);

    Thanks for the script!

    Meg

  18. amirul

    resume download not possible by our script.if i cancel download then nest time i can not download.so no resume capacity of our code.

  19. Alex

    Hi,

    I’m pretty sure i set it up correctly but am getting the following error:

    Download Key Generator
    Access denied for user ‘MYCPANELLOGINNAME_USERNAME’@’localhost’ to database ‘download’.

    I set all priviledges for the MYCPANELLOGINNAME_USERNAME to MYCPANELLOGINNAME_database? What am i doing wrong?

  20. Pingback: Unique download links – Protect your downloads | James P Farrell

  21. gary

    very nice script…
    I’ve been using OSCommerce and sometimes my download links fail, so i set up using linklok… this is good but gives a time period as opposed to download limits… which gets abused from time to time!

    I’ve managed to set up the script to point to zip-folders in a different location using…
    ../path/to/folder/item.zip
    this works without problems.

    I’ve tested it and sometimes i get the compression failed notice when the download process is complete.. I retry and sometimes it works…

    but the bigger the zip folder (130mb) in one case… it just keeps failing.

    its great as a backup to manually email links…
    thank you

  22. gary

    a quick update… as i couldn’t settle for 130mb failing…
    i have now managed to successfully download more than 10 files in a row…
    230mb being the biggest. the others around the 150mb mark.
    i searched the internet madly… everyone seems to think php scripts timeout… possibly true!
    anyways… using the fakename left me with loads failed decompresssions… (using zip)… i even uploaded new zips without compressing them to no avail!
    when i changed it to real name i figured there was some kind of cache memory causing an issue… still not sure about this… but as my downloads are in external folders it doesn’t matter that the real name is used…
    After downloading all my files… further attempts seem to fail… leading me back to the cache being corrupted or something.
    however… this morning i woke up and successfully downloaded them all again!
    i have amended the code slightly… just found other headers that people seem to use…
    they may not take effect immediately you change them as i think memory has to be flushed by the server… which most of us are probably sharing with other web sites. (hence the overnight allowing me to repeat my success).
    I’ve changed the headers to read…

    ob_start();
    $mm_type="application/octet-stream";
    header("Expires: 0");
    header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
    header("Pragma: no-cache");
    header("Content-Type: " . $mm_type);
    header("Content-Length: " .(string)(filesize($realfilename)) );
    header('Content-Disposition: attachment; filename="'.$realfilename.'"');
    header("Content-Transfer-Encoding: binaryn");
    set_time_limit(0);
    ob_end_clean();
    readfile($realfilename);

    and i increased my
    session.gc_maxlifetime
    that my server allows me to do…
    i keep trying other tweaks… but impatience leads to frustration!!!!!
    hope this helps someone.

  23. Alex

    Not sure if you’re checking these still, but it all works fine apart from the limit.. I can only download the file once, and then it expires.. even if i set it to any other number, it will only download it once.. any idea what this could be? Thanks

  24. Drew

    Thank you for this it works perfectly. I did do a little tweaking however. And for anyone who is looking to use this for OTA downloads for blackberry devices this is the header you will need to use:

    header('Content-Type: text/vnd.sun.j2me.app-descriptor');
  25. Mike

    I think that download.php always uses the default maxdownloads from the config file.
    Does not use the value from the mysql database.

    Add $maxdownloads = $row[‘maxdownloads’];

    Either just before or after the $downloads = $row[‘downloads’];

    Thanks, works great.

  26. lebisol

    Thanks for sharing your code, this is really cool.
    I am having some issues implementing it thought, after running some tests I started getting errors as below.
    —-
    Warning: Cannot modify header information – headers already sent by (output started at /home/user/public_html/files/download.php:12) in /home/user/public_html/files/download.php on line 109
    … on line 110
    … on line 111
    … on line 112
    —-

    Not sure the problem is as initially the script worked as customized.
    My ‘customization’ is really only in fact that I moved the form into root index file – a folder above the ‘files’ folder with form action being ‘files/index.php’ and made the variables static so that ‘note’ is the only field that gets submitted. Download count, file number and time is fixed. Not sure if this throwing of the headers.
    Any ideas?
    Thank you.

  27. ken

    is it possible instead of download to set it to open and print a single copy ? I want my user to be able to open the .zip and print once…..

  28. ardamis Post author

    The best you can do, at least for Windows users, is to cause the browser to prompt the user to Open or Save the file. Both choices save the file to the machine, but Open then causes the OS to perform the Open function on the file using the default application associated with that file type (a .PDF will open in Reader, while a .DOCX will open in Word, for example).

    The browser has no control over how the file is opened or what happens afterward.

    In the case of a zip file, an Open would probably just be a prompt for a location for the extracted files.

  29. Maurice

    Hi,

    Our school site will offer a complete album of our choir. 20 songs = 20 different mp3 files. With your code, I have to generate a key 20 times for each customer. Would it be possible to have only one key for all the downloads?

    Thank you!

  30. Robert

    Hi, Just wanterd to say thanks! Haven’t tried it yet, but will do so pretty soon. I don’t know much about this kind of coding. So this will help a lot! =)

  31. Mark

    Hi,
    I really like this code it is a huge help but…

    I have the “big filesize” problem.
    I have tested this and over about 100Mb for me it will just give me instant result as 0 Mb zip file.
    If it is only let’s say 70MB it works perfect.
    Can someone advise how to get around this, I read the change header script above but to be 100% honest do not understand much of it.
    I can’t even find “header” part of the coding.

    Please if soemone could help me out please.

    Thanks

  32. Mohamed alam

    I have 100 mp3 songs. after purchasing 2 or 3 different songs. customer should be able to download them using key generated link . which will be emailed by me to the customer. How can i do that using your download.php script

  33. Mohamed alam

    There is option for me after purchasing customer can download the songs from his myaccount section. but i want to send an email to customer to download songs from link with key generated. It should expire after 48 hours. the song purchase is dynamic.

  34. Jim Munroe

    Hey there — this does 99% of what I need it to do, but I need to be able to point to an external file rather than one locally. Any ideas?

  35. Jim Munroe

    OK, I figgered it — just hardcoded it into download.php

    $realfilename = "http://whatever.com/song.mp3";

    I only have the one file at the moment so it works fine!

    Thanks a ton, Ardamis!

  36. Jim Munroe

    Hey Oliver– I have this script hosted on a friend’s server but pulling the 2Gb download from an external source (a CDN). However, he’s reported high bandwidth usage which is not desirable. Is it possible the 2Gb download is going through his connection somehow?

    One thing I’ve come across when using this script that might be of use to your users. I was originally having problems with the download stopping after about an hour for a 2Gb file, and when I checked with my webhost I discovered they had a cron job silently killing any php processes that have gone longer than an hour. So if people are having trouble with that, they may want to consult their webhost and find another place to host the php file.

  37. ardamis Post author

    It seems unlikely that a file on a CDN is being somehow channeled through his web site’s hosting. That would defeat the purpose of the CDN, which is supposed to reduce load on the host by serving files from a location geographically near the user agent making the request.

    If your Apache installation supports it, you can take PHP out of the picture and instruct the server to send the file. This should alleviate problems with PHP timing out on large files. Here’s a good place to start learning about Apache’s “mod_xsendfile” module: http://codeutopia.net/blog/2009/03/06/sending-files-better-apache-mod_xsendfile-and-php/

    1. Raphael Essoo-Snowdon

      Having a problem with filesize too. Has anyone worked this out? I can download a 1.3GB file fine, but a 7GB file is failing for some reason.

  38. nikos

    Hi there.

    I managed to get the script going, its connecting tot he DB, its generating keys etc…
    When i try the download link it generates, i get a popup asking me to save/open/etc and when i click on save, nothing happens at all. The download never starts (not even after 20 mins), and the page is just white. Its a zip file.
    Any ideas please?

    Cheers,
    Nikos

  39. Nikos

    I would like to add to my previous post above that i figured out it has something to do with file size. The file in question has 320mb…. but if i take your example _1.zip it works fine.

    In your code you have written:


    // Consider http://www.php.net/manual/en/function.header.php#86554 for problems with large downloads

    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . basename($fakefilename) . '"');
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($realfilename));
    ob_clean();
    flush();
    readfile($realfilename);
    exit;

    at the bottom of download.php.

    So taking that link you have there into consideration for larger file sizes from http://www.php.net/manual/en/function.header.php#86554 with:


    header("Content-Disposition: attachment; filename=" . urlencode($file));
    header("Content-Type: application/force-download");
    header("Content-Type: application/octet-stream");
    header("Content-Type: application/download");
    header("Content-Description: File Transfer");
    header("Content-Length: " . filesize($file));
    flush(); // this doesn't really matter.

    $fp = fopen($file, "r");
    while (!feof($fp))
    {
    echo fread($fp, 65536);
    flush(); // this is essential for large downloads
    }
    fclose($fp);

    I tried all different combinations of implementing it with your current download.php, but I have had no luck what so ever.

    Please help me fix this issue, since your script is really usefull, but most of my files will be rather large (between 100MB and 3GB).

    Cheers.

    1. Raphael Essoo-Snowdon

      Did you manage to work this out Nikos? I’m running into the exact same problem.

  40. Dave

    Hi,
    I’ve been out of this for over 15yrs. Now I’m trying to fire up the brain cells. I’ve set up the config.php but still get the index poping up. I’ve been trying to created the table in the mysql data base with myphp in cpanel but I’m have a real time wrapping my brain around setting up the data base with the above example. I learn quick when I can see exactly what needs to be done. Can someone break it down for a returning newbie.

    1 CREATE TABLE `downloadkeys` (
    2 `uniqueid` varchar(12) NOT NULL default ”,
    3 `timestamp` INT UNSIGNED,
    4 `lifetime` INT UNSIGNED,
    5 `maxdownloads` SMALLINT UNSIGNED,
    6 `downloads` SMALLINT UNSIGNED default ‘0’,
    7 `filename` varchar(60) NOT NULL default ”,
    8 `note` varchar(255) NOT NULL default ”,
    9 PRIMARY KEY (uniqueid)
    10 );

    Where are the table names, var, null, etc… I see them but they look like they are all running together.
    Thanks for any help;
    Dave

  41. Tam Nguyen Photography

    As Mike said earlier, there’s a bug in the code. The download.php page always takes in the default maxdownloads, which is 2. You have to modify download.php:56 to having this line below to make it work:

    $maxdownloads = $row[‘maxdownloads’];

    Other than that, great script!

  42. Milad

    Hi Oliver,

    First of all thank you for sharing this!!! I have two questions.

    1:
    Is it possible to see if a download has been succeeded? (just a Yes or No in the report)
    This way you can prevent users from lying to support with “my download has failed”.

    2:
    Is it possible to automatically delete used URLs form the database?
    For example 1 week/month after their expire date.
    This way you end up with a clean database and prevent timeouts.

    Thanks Oliver,

    Milad

  43. Milad

    For the ones that are interested in the answer of my question 2 from the comment above, I managed to automatically delete old URLs with a Cronjob.

    Create a file “name.php” with the code below.
    The code will delete URLs that are older than 2419200 seconds (1 Month).

     
    <?php 
    	require ('config.php');
    	
    	$query = "DELETE FROM downloadkeys WHERE `timestamp` < (UNIX_TIMESTAMP() - 2419200)";
    	$result = mysql_query($query) or die(mysql_error());	
    ?>
    

    Now Login to your Web control panel and create a Cronjob.
    In my case the path to my file is: (leave the space between “php /home”)

     
    /usr/local/bin/php /home/[username]/domains/[your domain]/public_html/[path to file]/name.php
    

    The Cronjob is scheduled as follows:
    55 23 1 * *
    This means that the Cronjob will run the first day of every month at 23:55 hours.

    If you want to see which URLs are going to be deleted change line 20 in “report.php” to:

     
    $query = "SELECT * FROM downloadkeys WHERE `timestamp` < (UNIX_TIMESTAMP() - 2419200)";
    

    I’am not a programmer and the method above is not something that a real programmer will use to deleted records from a database. But it works in this case and its good enough for me :).

  44. piscator

    Your script does the exact thing i have been looking for. My problem is, that i would need this combined with a form where a visitor can enter his email and get the downloadlink sent to him directly.
    This surely is no problem for people with actual php-knowledge, but it exceeds my knowledge by far.
    It would be greatly appreciated if anyone could give me a hint.

  45. MattVogt

    Hello! Is it possible to generate new expiring keys on the fly? For like a receipt email or something?

    For example – you have a 100 customers, you have create 100 keys? What do you do?

    Thanks,
    Matt

  46. skullmonkeu

    TOP NOTCH script! THANKS 😀

    One thing, any way to add infinite time availability?

    Thanks,
    S@

  47. espo74

    Multiple File Names

    I know, I know! this is awesome. I have been using it for a few years now…and just came into a new situation. I know we can assign multiple files for different keys, but they all end up having the same $fakefilename. Is it possible to assign a different $fakefilename to each generated file/key? I have three different files that I am working with and rather than have each end up with the same $fakefilenameI would like to assign a specific one to each.

    I will go through this all again and see if the solution is there and i missed it, but I don’t think that it was in here and I am not skilled enough to modify.

  48. Ebrahim

    Hi,

    I have tried with creating db, dbuser, pass but failed. Here is what i got:

    Fatal error: Uncaught Error: Call to undefined function mysql_connect() in C:\xampp\htdocs\md\config.php:25 Stack trace: #0 C:\xampp\htdocs\md\generatekey.php(39): require() #1 {main} thrown in C:\xampp\htdocs\md\config.php on line 25

    any help?

  49. Sam C

    @Ebrahim
    mysql_connect() was depreciated in Php 7.0 which I am assuming you are using.
    Try replacing mysql_connect() with mysqli_connect() example:
    mysqli_connect(“127.0.0.1″,”root”,”pass”,”your_database”)

  50. Sam C

    This script would be even more awesome if we could log the users IP and allow only up to 3 IPs!
    $_SERVER[‘REMOTE_ADDR’]

  51. John

    Hi ardamis,
    Hi everybody,

    DB created without problems and I also made the entries on config.php. I uploaded the files and everything in one folder in my www path on server. Now if I go on index.html I can’t reach for a test download, because there is only this showing up (as it is coded in index.html provided by the zip):
    “No peeking at the folder contents”
    “Psst. Set your variables in config.php”
    As I told I already did the settings on the config file. Further more. If I go to the renamed generatekey.php there is no key generated or provided. Only text: “Download Key Generator” is showing up. Any ideas? Perhaps the script isn’t compatible with latest PHP 7.2 . Any chance to make it run again?
    Greetings from Germany. Best regards, John

  52. schnydszch

    Hi! I came across this script and was able to make it work in 7.x except for the download, I am getting a white screen. Are the headers or some of the headers in the download.php already deprecated?Thanks and cheers!

  53. schnydszch

    hi! Please disregard the my first comment, I was able to make it work in php 7.x. 🙂 Thanks for this awesome creation. 🙂

Comments are closed.