Ever wonder how to create a download link in #PHP and then make it expire? Would you like to know how to expire a download link after a set number of times they download it? Do you want to know how to protect your files from people trying to steal your downloads? We are going to answer those questions and more on this tutorial. 

#phpLessons #MySQL


Setting Up The Database For Expired Links

Set up your database first. Create a database and then use the following code to set up the table and rows. Let me tell you what each row is going to do. The link row is going to save an encrypted link you will use for your application. This will appear in the URL address bar. The file is going to be the name of the file you are uploading for a user to download. You can keep track of how many times you allow a file to be downloaded by using the counting row. The expire row is going to keep track of the time you set for the link to expire. The tstamp row is going to keep track of the time that you uploaded the file.  
CREATE TABLE `links` (
`id` int(11) NOT NULL,
`link` char(40) NOT NULL,
`file` text NOT NULL,
`counting` int(11) NOT NULL DEFAULT 11,
`expire` int(11) NOT NULL,
`tstamp` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;;
 

For Future Projects

Keep in mind this tutorial is showing you how to do something like this. In the future, you can build on this further to create purchases or user activations on a website or app.

File To Create Expired Download Link

Here are the complete files to create expired download links in PHP. Now let's talk about the files so you understand what they do.

Index File To Start Process

The index.php file is there to start the process. You can name it anything you want. It looks like this when you open it to your editor. See the video for detailed explanations.
<?php include('header.php');
if(isset($_POST['submit'])){
   $errors= array();
      $file_name = $_FILES['file']['name'];
      $file_size =$_FILES['file']['size'];
      $file_tmp =$_FILES['file']['tmp_name'];
      $file_type=$_FILES['file']['type'];
    $fileend=explode('.',$file_name);
      $file_ext=strtolower(end($fileend));

      $extensions= array("jpeg","jpg","png","pdf", "zip");

      if(in_array($file_ext,$extensions)=== false){
         $errors[]="extension not allowed, please choose a JPEG, PNG, ZIP or PDF file.";
      }

      if($file_size > 2097152){
         $errors[]='File size must be under 2 MB';
      }

      if(empty($errors)==true){
         move_uploaded_file($file_tmp,"files/".$file_name);
         //echo "Success";
      }else{
         print_r($errors);
      }


$expire=$_POST['date'];
$counting=$_POST['counting'];
$date = date('M d, Y h:i:s A', strtotime($expire));
$dbdate = date('Y M d H:i:s', strtotime($expire));
$one= 'To Expire on '.$date.'<br/>';
$d = DateTime::createFromFormat(
    'Y M d H:i:s',
    $dbdate,
    new DateTimeZone('EST')
);

if ($d === false) {
    die("Incorrect date string");
} else {
    $expiredate=$d->getTimestamp();
}

$link = sha1(uniqid($file_name, true));

$tstamp=$_SERVER["REQUEST_TIME"];

mysqli_query($db,"INSERT INTO links(`link`,`file`, `counting`, `expire`, `tstamp`)
VALUES ('$link', '$file_name', '$counting','$expiredate','$tstamp')");

$two= '<a href="download.php?link='.$link.' " target="_NEW">Link</a>';
}
?>
<div class="container">
<div class="jumbotron"><p class="text-xl-center"><?php if(isset($one)){echo $one.$two;};?></p></div>
<h1 class="animated bounce"><span class="glyphicon glyphicon-link"></span>Generate A Link That Expires</h1>
<div class="row">
    <div class="col-sm-4"></div>
    <div class="col-sm-4">
  <form method="post" role="form" enctype="multipart/form-data">
  <div class="form-group">
  <label for="file">Select File:</label>
  <input type="file" class="form-control" name="file" required>
  </div>
  <div class="form-group">
  <label for="counting">How Many Times Can Link Be Accessed?:</label>
  <input type="tel" class="form-control" name="counting" required>
  </div>
  <div class="form-group">
  <label for="date">Set Expiration Date and Time For Link:</label>
  <input type="datetime-local" class="form-control" name="date" required>
  </div>
  <input type="submit" name="submit" class="btn btn-success btn-lg" value="submit" />
  </form>
  </div>
    <div class="col-sm-4"></div>
</div>
</div>
<?php
include('footer.php');
?>
Now lets go to the download file on the next page.

The Download File

Here is the download.php file, this file is the one that actually keeps tracks of the expired links, times the files is downloaded and provides the download if they meet all conditions. It also contains comments if you were to add future users, keep track of purchases and more.  

<?php include('header.php'); ?>
<div class="container">
<div class="jumbotron"><p class="text-xl-center">
<?php
// retrieve link
if (isset($_GET["link"]) && preg_match('/^[0-9A-F]{40}$/i', $_GET["link"])) {
$link = $_GET["link"];
}else{
echo "<h1>Valid link not provided.</h1>";
exit();
}
//starting verification with the $ct variable
$ct=0;
$currenttime= $_SERVER["REQUEST_TIME"];
$currentdate = date('M d, Y h:i:s A', $currenttime);
echo 'Current Date '.$currentdate.'<br/>';
// verify link get necessary information we will need to preocess request
$result = $db->query("SELECT * FROM links WHERE link='$link' ") ;
while ($row = $result->fetch_assoc()) {
$linkdb = $row['link'];
$filedownload = $row['file'];
$tstamp = $row['tstamp'];
$expire = $row['expire'];
$counting = $row['counting'];
$newcount=$counting-1;</pre>
//convert timestamp to readable date the show expiration date and time
$date = date('M d, Y h:i:s A', $expire);
echo 'To Expire on '.$date.'<br/>';

// Check to see if link has expired
if ($currenttime > $expire) {
echo "We are so sorry the link has expired.";
exit();
// delete link so it can't be used again
mysqli_query($db,"DELETE FROM links WHERE link='$link' ");
exit();
}

if ($linkdb==$link) {
echo 'You have '.$newcount.' more times to access this link.';
mysqli_query($db,"UPDATE links SET counting='$newcount' WHERE link='$linkdb' ");
$ct=1;
}
else {
echo "Valid link not provided or link has expired.";
exit();
}
}

// delete link so it can't be used again
mysqli_query($db,"DELETE FROM links WHERE link='$link' AND counting < '1' ");

//FILE DOWNLOAD
//path to file
if($ct==1){
$path = '';
$path = "files/$filedownload";
echo $path;

$mime_type=mime_content_type($path);

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$path.'"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($path)); //Absolute URL
ob_clean();
flush();
readfile($path); //Absolute URL
exit();
}else{
echo '<p>This file has already been dowloaded the maximum number of times.</p>';
}
?>
</p>
</div>
<?php
include_once('footer.php'); ?>
 

Header, Footer  and Config Files

Here is the header, footer and config.php  files to properly include scripts we need.

header.php

<?php
date_default_timezone_set('America/New_York');
include('config.php');
?>
<html>
<head>
<title>Create A Link That Expires</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" type="text/css" >
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
<link href="style.css" rel="stylesheet" type="text/css" >
</head>
<body>
 

footer.php

</body>
</html>
<?php
$db->close();
?>

config.php

<?php
$db = mysqli_connect("localhost","root","","test");
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}else{
echo "";
}
?>

Protect Your Files Folder

An important note is that you want to protect your files folder so that people cannot sneakily find out where you store your downloads, then just come and download all your files for free. You do this by including a htaccess file in the folder. I include it with the download files above. Here is what it looks like. Deny From All

Conclusion For Creating  Expired Download Links in PHP

I hope you could get some use from this tutorial. Please remember that you can build on it. There are many things that you can do with this script. Please give me some feedback and I will create more like this.

Alternative Tutorials To Expire Links In PHP

If I could not help, there are several other tutorials online for this process. I will link them here. [SOLVED] Creating Temporary Download Links - PHP Coding Help - PHP Freaks Generate download file link in PHP - Stack Overflow PHP Master | Generating One-Time Use URLs (sitepoint.com) One Time Temporary Download Link with Expiration in PHP - CodexWorld


Sign Up To Comment