Accessibility Navigation

ImageXY

ImageXY - Mac OS X Batch Photo Resizer

Checkout ImageXY - Painless image resizing for Mac OS X.

Quickly and painlessly bulk resize images, change image formats and create web-friendly photos for your website.

Available on the Mac App Store!

Creating One Time Download Links

Creating single use or timed download links can allow websites to offer downloadable content that expires after a single download or after a set period of time. Many e-commerce sites are using these techniques to sell documents and files online.

Graham, your other author here at Webvamp, has recently been working on a project where the client wanted to offer downloadable content to users that they could track and control access to. Due to the linking nature of the web this can be a difficult task if you just directly link to the file.

The user clicks on a link and views/downloads the file depending on if it can be displayed in the browser or not. Since the user is given direct access to the file, nothing is stopping them from sharing the link with other people and passing your content around to others. This is OK for free stuff, but not so great for content you are trying to sell. Directly linking to the file also makes it harder to keep statistics about how many times the file has been downloaded without crawling through your server logs.

In order to control access and gather information on the downloads he asked me how best to create a solution.

One Time Download Links

The solution is simple: offer unique download links.

Instead of directly linking to the file you want to download, you link to a download script that controls and manages the download process. You then have full control over any downloads you offer, allowing you to:

OK enough background, let’s see how to do it.

Show me the code!

The following code uses PHP and MySQL to offer a one time download link that lasts for 7 days. You can easily tweak it to meet your own needs and specifications.

SQL

CREATE TABLE downloads (
	downloadkey varchar(32) NOT NULL unique,
	file varchar(255) NOT NULL default '',
	downloads int UNSIGNED NOT NULL default '0',
	expires int UNSIGNED NOT NULL default '0'
);

PHP Code

//The directory where the download files are kept - keep outside of the web document root
$strDownloadFolder = "/downloads/";

//If you can download a file more than once
$boolAllowMultipleDownload = 0;

//connect to the DB
$resDB = mysql_connect("localhost", "username", "thisismypassword");
mysql_select_db("database", $resDB);

if(!empty($_GET['key'])){
	//check the DB for the key
	$resCheck = mysql_query("SELECT * FROM downloads WHERE downloadkey = '".mysql_real_escape_string($_GET['key'])."' LIMIT 1");
	$arrCheck = mysql_fetch_assoc($resCheck);
	if(!empty($arrCheck['file'])){
		//check that the download time hasnt expired
		if($arrCheck['expires']>=time()){
			if(!$arrCheck['downloads'] OR $boolAllowMultipleDownload){
				//everything is hunky dory - check the file exists and then let the user download it
				$strDownload = $strDownloadFolder.$arrCheck['file'];

				if(file_exists($strDownload)){

					//get the file content
					$strFile = file_get_contents($strDownload);

					//set the headers to force a download
					header("Content-type: application/force-download");
					header("Content-Disposition: attachment; filename=\"".str_replace(" ", "_", $arrCheck['file'])."\"");

					//echo the file to the user
					echo $strFile;

					//update the DB to say this file has been downloaded
					mysql_query("UPDATE downloads SET downloads = downloads + 1 WHERE downloadkey = '".mysql_real_escape_string($_GET['key'])."' LIMIT 1");

					exit;

				}else{
					echo "We couldn't find the file to download.";
				}
			}else{
				//this file has already been downloaded and multiple downloads are not allowed
				echo "This file has already been downloaded.";
			}
		}else{
			//this download has passed its expiry date
			echo "This download has expired.";
		}
	}else{
		//the download key given didnt match anything in the DB
		echo "No file was found to download.";
	}
}else{
	//No download key wa provided to this script
	echo "No download key was provided. Please return to the previous page and try again.";
}

The above code is very simple, consisting of several checks to make sure that the download key provided in the URL is valid and then the download code.

All you then need to do is add entries to the database that link to the downloadable files. You could do this as part of your checkout process if you are selling the downloads, or as part of a registration or form request etc. Below is a basic example.

function createKey(){
	//create a random key
	$strKey = md5(microtime());

	//check to make sure this key isnt already in use
	$resCheck = mysql_query("SELECT count(*) FROM downloads WHERE downloadkey = '{$strKey}' LIMIT 1");
	$arrCheck = mysql_fetch_assoc($resCheck);
	if($arrCheck['count(*)']){
		//key already in use
		return createKey();
	}else{
		//key is OK
		return $strKey;
	}
}

//get a unique download key
$strKey = createKey();

//insert the download record into the database
mysql_query("INSERT INTO downloads (downloadkey, file, expires) VALUES ('{$strKey}', 'onetimedownload.zip', '".(time()+(60*60*24*7))."')");

All you then need to do is provide a link to the download.

Seeing it in Action

You can see a working example of this by downloading a zip file of this code.

The above link will take you to another page that will provide you with a unique download link to a bundled copy of the code. This unique download link will allow you to download the content once within the next 7 days.

Download the Code.


About The Author

Jacob Wyke is a web developer from the UK who makes complex things simple on the internet. He develops a batch image resizer for Mac OS X called ImageXY which you should try if you ever need to resize anything for the web.

You should also follow him on twitter.