File download consists of front-end GUI and back-end code .
Caution: Never use include or require for uploaded files. Serve them as static or use file_get_contents(), readfile() etc.
Standard GUIAdvanced GUIBack-end
Standard Front-end Page
The Download form sends GET request to the back-end.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
div.form {
padding: 0.5rem 2rem 0;
background-color: #eee;
line-height: 1.8rem;
}
</style>
</head>
<body>
<div class="form">
<div>File Download Form</div>
<label>Download using link:</label><br />
<a href="download_handler.php?download=flowers.jpg">flowers.jpg</a><br />
<label>Download using javascript:</label><br />
<button onclick="download(this)">flowers.jpg</button>
</div>
<script>
function download(btn){
var fileName = btn.innerHTML;
window.location = 'download_handler.php?download=' + fileName;
};
</script>
</body>
</html>
Standard GUI Demo
The Download form may send GET or POST request to the server.
Click on button on link to download file
Advanced Front-end Page
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.download-form {
padding: 0.5rem 2rem 0.5rem;
background-color: #eee;
line-height: 1.8rem;
float:left;
}
.download-form-img {
width: 80px;
display: block;
margin: 0 auto;
cursor: pointer;
}
.download-form-floated {
float: left;
text-align: center;
padding:0.5rem;
}
.download-form-floated::after {
content: '';
clear:both;
}
.download-form-file-list {
margin-left: -0.5rem;
}
</style>
</head>
<body>
<div class="download-form">
<div style="font-weight:700;">File List Form</div>
<label>Get files list then click to download:</label><br />
<button onclick="get_list()">Get File List</button>
<div class="download-form-file-list"></div>
</div>
<script>
function send_get_request(url, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
callback(this);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
function get_list() {
var file_list = document.getElementsByClassName('download-form-file-list')[0];
file_list.innerHTML = '';
send_get_request("list_handler.php?list=all", function(result){
var myObj = JSON.parse(result.responseText);
for(var i in myObj) {
var file_name = myObj[i];
add_file_btn(file_list,file_name);
}
});
}
function add_file_btn(file_list,file_name) {
var file_div = document.createElement("DIV");
file_div.className = "download-form-floated";
file_list.appendChild(file_div);
var file_img = document.createElement("IMG");
file_img.className = "download-form-img";
file_div.appendChild(file_img);
file_img.src = "list_handler.php?list=" + file_name;
var file_cap = document.createElement("DIV");
file_cap.innerHTML = file_name;
file_div.appendChild(file_cap);
file_img.onclick = function() {
window.location = 'download_handler.php?download=' + file_name;
}
}
</script>
</body>
</html>
Advanced GUI Demo
code here
Download Handler
<?php
$downloadDir = './downloads';
require_once "FileDownloader.php";
new FileDownloader($downloadDir);
List Handler
<?php
//query download directory
$downloadsPath = './downloads';
$thumbsDir = 'thumbs';
if (isset($_GET['list'])) {
if ($_GET['list'] === 'all') {
//get sorted file array and filter '..' and '.'
$files = array_diff(scandir($downloadsPath), array('..', '.', $thumbsDir));
//return filenames to front-end as json
echo json_encode($files);
} else {
$fileName = filter_var($_GET['list'],FILTER_SANITIZE_FULL_SPECIAL_CHARS);
//replace non-image filenames with avatars
if (substr($fileName,-4)=='.pdf') {
$fileName = "pdf.png";
}
$filePath = "$downloadsPath/$thumbsDir/$fileName";
//return thumbs jpg or png
if (file_exists($filePath)) {
@readfile($filePath);
}
}
}
Download Class
<?php
class FileDownloader {
function __construct($downloadDir = '.')
{
if (isset($_GET['download'])) {
$fileName = filter_var($_GET['download'],FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$this->do_download("$downloadDir/$fileName");
}
}
private function do_download($filePath)
{ //check if file exists
if (!file_exists($filePath)) {
echo "File named <b>$filePath</b> does not exist.";
return;
}
//get mime type from file name extension
$fileExt = strtolower(substr(strrchr($filePath,"."),1));
switch ($fileExt) {
case "pdf": $mime="application/pdf"; break;
case "exe": $mime="application/octet-stream"; break;
case "zip": $mime="application/zip"; break;
case "doc": $mime="application/msword"; break;
case "xls": $mime="application/vnd.ms-excel"; break;
case "ppt": $mime="application/vnd.ms-powerpoint"; break;
case "gif": $mime="image/gif"; break;
case "png": $mime="image/png"; break;
case "jpe":
case "jpeg":
case "jpg": $mime="image/jpg"; break;
default: $mime="application/force-download";
}
//send headers and file contents
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: $mime");
header("Content-disposition: attachment; fileName=\"". basename($filePath) ."\"");
header("Set-Cookie: fileDownload=true; path=/ ");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . @filesize($filePath));
set_time_limit(0);
@readfile($filePath);
exit;
}
}
