PHP Force Download PDF, Video, Image, CSV
- By Gurunatha Dogi in PHP
- May 10th, 2014
- 50053
- 3
About PHP Download (Force-Download) Script
In this article we will see how to force download text, rich format text, images, videos, pdfs, tar zip, word document (doc, docx), excel (xls, xlsx), powerpoint, mp3, mp4, audio or any file or application using a simple PHP script. This script can download any file from local server location or from remote server location.
The PHP Force Download Script is designed or programmed in such a way that you can download any file or application available in the internet media. In this article we have try to cover almost all mime-types (media types) available in the internet. You can download microsoft excel, microsoft word, powerpoint (2003 to 2010) versions, pdfs, zip files, media files, videos, audios, mp3, mp4, 3gp, text files, rich formatted text, images (jpeg, gif, png, bmp) almost anything you can download from same server (local server) or from remote server.
Script is designed with php scripting language which changes browser http headers content-type from loading/writing to force-download. Means file will not displayed on the browser but it prompt directly to force download.
The advantages of using php force-download script that you can hide direct url of the file, you can count the number of downloads, track and log the ip of the user who downloading that file/video, Authenticate and authorize the users for downloading files, you can encrypt and decrypt file path and file name on downloading, you can download the files from remote server, If you are developing any website which includes download manager to download songs, movies, applications, files, pdfs, zip files or any thing then force-download script is very useful.
Script is so flexible that it can download file from remote server or from same server location in chunkwise without loading server.
How to use PHP to Force Download Any File
We will create a new php function with four input values i.e. file url or file path, new file name (customized name), Internet media type (MIME types), boolean value to specify url is located in remote server or local server.
<?php function DownloadAnything($file, $newfilename = '', $mimetype='', $isremotefile = false){ //some code } ?>
Our download php function name is "DownloadAnything()" with four input values.
$file = File url or file path which you want to download.$newfilename = It is optional value this you can keep blank or you can specify any new custom name from downloading a file with that custom name.
$mimetype = Internet media type (This is optional you can leave blank) or you can specify internet media type of a file which you want to download.
$isremotefile = Boolean value by default false (Means file will be downloaded from local server only). True to download the file from remote server location.
Kindly Note : Downloading from remote server can cause an error while downloading, you can download small files with less than 10MB but to download huge files from remote location sometimes can cause an error or incomplete it will download. This happens due to server security or connection timeout from the remote server. Downloading small files (< 5MB) from remote server will not create any download issue it will download fine.
In the next step inside function we will create two variables i.e.
<?php $formattedhpath = ""; $filesize = ""; ?>$formattedhpath : To check weather $file variable string is of file-path or with complete file url i.e. with url with domain-name.
$filesize : To calculate the size of file to specify http headers Content-Length.
Before doing any thing inside the function first we will check that input $file variable string is specified or not. If we dont check weather the variable is empty or not then it will throw an exception error on the user screen.
<?php if(empty($file)){ die('Please enter file url to download...!'); exit; } ?>
Once we verified the $file string now lets remove spaces if present in the $file variable and replacing it with the "%20" which is the ascii encoded value for a space in a URL string or file-path string.
<?php function RemoveUrlSpaces($url){ $url = preg_replace('/\s+/', '%20', trim($url)); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); return $url; } ?>
To remove spaces and replacing it with the ascii code we have created a new separate function called "RemoveUrlSpaces()" which takes file-path or file url as string and replaces with spaces with ascii %20.
The new above function we have called inside the "DownloadAnything()" function as shown below.
<?php //Removing spaces and replacing with %20 ascii code $file = RemoveUrlSpaces($file); ?>
Now further step we will check weather that file is readable or not. If file is readable or present then only we can download that file.
<?php if($formattedhpath == "url"){ $file_headers = @get_headers($file); if($file_headers[0] == 'HTTP/1.1 404 Not Found') { die('File is not readable or not found...!'); exit; } }elseif($formattedhpath == "filepath"){ if(@is_readable($file)) { die('File is not readable or not found...!'); exit; } } ?>
As you see from above code that we have used the two methodology to check file is readable or not. If $file string is url then we used "get_headers()" function to check file status.
If $file string is folder path or file-name then we used "is_readable()" function to check file status.
We use two methodology because "is_readable()" function can work only if string is folder path or file name and "get_headers()" can work only if string is proper url.
Get File Size in PHP from url
In order to get file size from url we need to use php get_headers() function which will return Content-Length of the file (File size) in array format.
<?php $data = @get_headers($file, true); $filesize = (int)$data["Content-Length"]; ?>
This above technique we applied for both urls. i.e. Same server url or remote server url.
PHP Get file size of remote file
If php "get_headers()" function failed to retrive the file size from the remote server location then we have used advance and powerful cURL approach to retrive file size.
PHP cURL() to get remote file size<?php ///If get_headers fails then try to fetch filesize with curl $ch = @curl_init(); if(!@curl_setopt($ch, CURLOPT_URL, $file)) { @curl_close($ch); @exit; } @curl_setopt($ch, CURLOPT_NOBODY, true); @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @curl_setopt($ch, CURLOPT_HEADER, true); @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); @curl_setopt($ch, CURLOPT_MAXREDIRS, 3); @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); @curl_exec($ch); if(!@curl_errno($ch)) { $http_status = (int)@curl_getinfo($ch, CURLINFO_HTTP_CODE); if($http_status >= 200 && $http_status <= 300) $filesize = (int)@curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); } @curl_close($ch); ?>
cURL is a powerful, faster and advanced method to read the content from remote server and as well as to get file size from the remote server.
"get_headers()" function and
function will not work if the $file string is having folder like path. So if the $file string is folder-path then we have used a normal and reliable php i.e. "filesize()" function to the retrive filesize. "filesize()" function will only work if the string is like folder-path and cannot work if string is url.
(Internet Media) MIME Media Types List
We have "DownloadAnything()" where thrid input type option is to input mime type of a file which you want to download. Now if you specify any mime media type then the file will be downloaded as per that mime type. If you do not specify any mime type of a file then as per the extension it will try to refer that particular mime type which we have specified in the code.
Get extension of File<?php ///Get the extension of the file $path_parts = @pathinfo($file); $myfileextension = $path_parts["extension"]; ?>
$myfileextension gets the extension of the file now as per the extension we assigned the mime media types. In this code we tried to cover almost every media type available on the internet if we are missing any media type in the code kindly feel free to let us know about that missing the media type in the comments section.
<?php $myfileextension = $path_parts["extension"]; switch($myfileextension) { ///Image Mime Types case 'jpg': $mimetype = "image/jpg"; break; case 'jpeg': $mimetype = "image/jpeg"; break; case 'gif': $mimetype = "image/gif"; break; case 'png': $mimetype = "image/png"; //..... ///Complete code is shown below } ?>
Downloading script uses alot of server usage. so lets decrease server usage by turning off output buffering using "ob_end_clean()" function.
<?php @ob_end_clean(); ?>
Now we have all values that we wanted to pass to http headers like filesize, mime-type and file name. So lets pass all the values to http headers.
<?php header('Content-Description: File Transfer'); header('Content-Type: '.$mimetype); header('Content-Disposition: attachment; filename='.$newfilename.''); header('Content-Transfer-Encoding: binary'); header("Expires: Wed, 07 May 2013 09:09:09 GMT"); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); header('Cache-Control: post-check=0, pre-check=0', false); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Pragma: no-cache'); header('Content-Length: '.$filesize); ?>
As you see from above code that we set header with no-cache means it will not cache the page. If you want to cache the page then specify the proper header. Header content description is file transfer, encoding in binary, with content-length as filesize, cache-control as no-cache and header modification as date.
Finally now its time to download the file in chunkwise without loading server. In this example we will download 1 MD per chunk.
<?php $chunk = 1 * (1024 * 1024);///1 Mb chunkwise $nfile = @fopen($file,"rb"); while(!feof($nfile)) { print(@fread($nfile, $chunk)); @ob_flush(); @flush(); } @fclose($filen); ?>
As you see from above code that we are opening file using "fopen()" method, reading file using "fread()" function 1 MB chunk wise till the end of file using while loop and
file. "ob_flush()" and "flush()" functions to free up the server usage or output buffering.
So friends this all about the use of php script to force-download any file, pdfs, zip, mp4, mp3, doc, docx, xls, xlsx, csv, text, image etc. Below find the complete source code of Force-Download using php. If you like this post useful kindly share it with your friends or office colleagues on social media networks.
Complete Source of PHP Force-Download<?php function RemoveSpaces($url){ $url = preg_replace('/\s+/', '-', trim($url)); $url = str_replace(" ","-",$url); $url = str_replace(" ","-",$url); $url = str_replace(" ","-",$url); $url = str_replace(" ","-",$url); $url = str_replace(" ","-",$url); $url = str_replace(" ","-",$url); $url = str_replace(" ","-",$url); $url = str_replace(" ","-",$url); $url = str_replace(" ","-",$url); return $url; } function RemoveUrlSpaces($url){ $url = preg_replace('/\s+/', '%20', trim($url)); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); $url = str_replace(" ","%20",$url); return $url; } function DownloadAnything($file, $newfilename = '', $mimetype='', $isremotefile = false){ $formattedhpath = ""; $filesize = ""; if(empty($file)){ die('Please enter file url to download...!'); exit; } //Removing spaces and replacing with %20 ascii code $file = RemoveUrlSpaces($file); if(preg_match("#http://#", $file)){ $formattedhpath = "url"; }else{ $formattedhpath = "filepath"; } if($formattedhpath == "url"){ $file_headers = @get_headers($file); if($file_headers[0] == 'HTTP/1.1 404 Not Found') { die('File is not readable or not found...!'); exit; } }elseif($formattedhpath == "filepath"){ if(@is_readable($file)) { die('File is not readable or not found...!'); exit; } } //Fetching File Size Located in Remote Server if($isremotefile && $formattedhpath == "url"){ $data = @get_headers($file, true); if(!empty($data['Content-Length'])){ $filesize = (int)$data["Content-Length"]; }else{ ///If get_headers fails then try to fetch filesize with curl $ch = @curl_init(); if(!@curl_setopt($ch, CURLOPT_URL, $file)) { @curl_close($ch); @exit; } @curl_setopt($ch, CURLOPT_NOBODY, true); @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); @curl_setopt($ch, CURLOPT_HEADER, true); @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); @curl_setopt($ch, CURLOPT_MAXREDIRS, 3); @curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); @curl_exec($ch); if(!@curl_errno($ch)) { $http_status = (int)@curl_getinfo($ch, CURLINFO_HTTP_CODE); if($http_status >= 200 && $http_status <= 300) $filesize = (int)@curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); } @curl_close($ch); } }elseif($isremotefile && $formattedhpath == "filepath"){ die('Error : Need complete URL of remote file...!'); exit; }else{ if($formattedhpath == "url"){ $data = @get_headers($file, true); $filesize = (int)$data["Content-Length"]; }elseif($formattedhpath == "filepath"){ $filesize = (int)@filesize($file); } } if(empty($newfilename)){ $newfilename = @basename($file); }else{ //Replacing any spaces with (-) hypen $newfilename = RemoveSpaces($newfilename); } if(empty($mimetype)){ ///Get the extension of the file $path_parts = @pathinfo($file); $myfileextension = $path_parts["extension"]; switch($myfileextension) { ///Image Mime Types case 'jpg': $mimetype = "image/jpg"; break; case 'jpeg': $mimetype = "image/jpeg"; break; case 'gif': $mimetype = "image/gif"; break; case 'png': $mimetype = "image/png"; break; case 'bm': $mimetype = "image/bmp"; break; case 'bmp': $mimetype = "image/bmp"; break; case 'art': $mimetype = "image/x-jg"; break; case 'dwg': $mimetype = "image/x-dwg"; break; case 'dxf': $mimetype = "image/x-dwg"; break; case 'flo': $mimetype = "image/florian"; break; case 'fpx': $mimetype = "image/vnd.fpx"; break; case 'g3': $mimetype = "image/g3fax"; break; case 'ief': $mimetype = "image/ief"; break; case 'jfif': $mimetype = "image/pjpeg"; break; case 'jfif-tbnl': $mimetype = "image/jpeg"; break; case 'jpe': $mimetype = "image/pjpeg"; break; case 'jps': $mimetype = "image/x-jps"; break; case 'jut': $mimetype = "image/jutvision"; break; case 'mcf': $mimetype = "image/vasa"; break; case 'nap': $mimetype = "image/naplps"; break; case 'naplps': $mimetype = "image/naplps"; break; case 'nif': $mimetype = "image/x-niff"; break; case 'niff': $mimetype = "image/x-niff"; break; case 'cod': $mimetype = "image/cis-cod"; break; case 'ief': $mimetype = "image/ief"; break; case 'svg': $mimetype = "image/svg+xml"; break; case 'tif': $mimetype = "image/tiff"; break; case 'tiff': $mimetype = "image/tiff"; break; case 'ras': $mimetype = "image/x-cmu-raster"; break; case 'cmx': $mimetype = "image/x-cmx"; break; case 'ico': $mimetype = "image/x-icon"; break; case 'pnm': $mimetype = "image/x-portable-anymap"; break; case 'pbm': $mimetype = "image/x-portable-bitmap"; break; case 'pgm': $mimetype = "image/x-portable-graymap"; break; case 'ppm': $mimetype = "image/x-portable-pixmap"; break; case 'rgb': $mimetype = "image/x-rgb"; break; case 'xbm': $mimetype = "image/x-xbitmap"; break; case 'xpm': $mimetype = "image/x-xpixmap"; break; case 'xwd': $mimetype = "image/x-xwindowdump"; break; case 'rgb': $mimetype = "image/x-rgb"; break; case 'xbm': $mimetype = "image/x-xbitmap"; break; case "wbmp": $mimetype = "image/vnd.wap.wbmp"; break; //Files MIME Types case 'css': $mimetype = "text/css"; break; case 'htm': $mimetype = "text/html"; break; case 'html': $mimetype = "text/html"; break; case 'stm': $mimetype = "text/html"; break; case 'c': $mimetype = "text/plain"; break; case 'h': $mimetype = "text/plain"; break; case 'txt': $mimetype = "text/plain"; break; case 'rtx': $mimetype = "text/richtext"; break; case 'htc': $mimetype = "text/x-component"; break; case 'vcf': $mimetype = "text/x-vcard"; break; //Applications MIME Types case 'doc': $mimetype = "application/msword"; break; case 'xls': $mimetype = "application/vnd.ms-excel"; break; case 'ppt': $mimetype = "application/vnd.ms-powerpoint"; break; case 'pps': $mimetype = "application/vnd.ms-powerpoint"; break; case 'pot': $mimetype = "application/vnd.ms-powerpoint"; break; case "ogg": $mimetype = "application/ogg"; break; case "pls": $mimetype = "application/pls+xml"; break; case "asf": $mimetype = "application/vnd.ms-asf"; break; case "wmlc": $mimetype = "application/vnd.wap.wmlc"; break; case 'dot': $mimetype = "application/msword"; break; case 'class': $mimetype = "application/octet-stream"; break; case 'exe': $mimetype = "application/octet-stream"; break; case 'pdf': $mimetype = "application/pdf"; break; case 'rtf': $mimetype = "application/rtf"; break; case 'xla': $mimetype = "application/vnd.ms-excel"; break; case 'xlc': $mimetype = "application/vnd.ms-excel"; break; case 'xlm': $mimetype = "application/vnd.ms-excel"; break; case 'msg': $mimetype = "application/vnd.ms-outlook"; break; case 'mpp': $mimetype = "application/vnd.ms-project"; break; case 'cdf': $mimetype = "application/x-cdf"; break; case 'tgz': $mimetype = "application/x-compressed"; break; case 'dir': $mimetype = "application/x-director"; break; case 'dvi': $mimetype = "application/x-dvi"; break; case 'gz': $mimetype = "application/x-gzip"; break; case 'js': $mimetype = "application/x-javascript"; break; case 'mdb': $mimetype = "application/x-msaccess"; break; case 'dll': $mimetype = "application/x-msdownload"; break; case 'wri': $mimetype = "application/x-mswrite"; break; case 'cdf': $mimetype = "application/x-netcdf"; break; case 'swf': $mimetype = "application/x-shockwave-flash"; break; case 'tar': $mimetype = "application/x-tar"; break; case 'man': $mimetype = "application/x-troff-man"; break; case 'zip': $mimetype = "application/zip"; break; case 'xlsx': $mimetype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; break; case 'pptx': $mimetype = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; break; case 'docx': $mimetype = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; break; case 'xltx': $mimetype = "application/vnd.openxmlformats-officedocument.spreadsheetml.template"; break; case 'potx': $mimetype = "application/vnd.openxmlformats-officedocument.presentationml.template"; break; case 'ppsx': $mimetype = "application/vnd.openxmlformats-officedocument.presentationml.slideshow"; break; case 'sldx': $mimetype = "application/vnd.openxmlformats-officedocument.presentationml.slide"; break; ///Audio and Video Files case 'mp3': $mimetype = "audio/mpeg"; break; case 'wav': $mimetype = "audio/x-wav"; break; case 'au': $mimetype = "audio/basic"; break; case 'snd': $mimetype = "audio/basic"; break; case 'm3u': $mimetype = "audio/x-mpegurl"; break; case 'ra': $mimetype = "audio/x-pn-realaudio"; break; case 'mp2': $mimetype = "video/mpeg"; break; case 'mov': $mimetype = "video/quicktime"; break; case 'qt': $mimetype = "video/quicktime"; break; case 'mp4': $mimetype = "video/mp4"; break; case 'm4a': $mimetype = "audio/mp4"; break; case 'mp4a': $mimetype = "audio/mp4"; break; case 'm4p': $mimetype = "audio/mp4"; break; case 'm3a': $mimetype = "audio/mpeg"; break; case 'm2a': $mimetype = "audio/mpeg"; break; case 'mp2a': $mimetype = "audio/mpeg"; break; case 'mp2': $mimetype = "audio/mpeg"; break; case 'mpga': $mimetype = "audio/mpeg"; break; case '3gp': $mimetype = "video/3gpp"; break; case '3g2': $mimetype = "video/3gpp2"; break; case 'mp4v': $mimetype = "video/mp4"; break; case 'mpg4': $mimetype = "video/mp4"; break; case 'm2v': $mimetype = "video/mpeg"; break; case 'm1v': $mimetype = "video/mpeg"; break; case 'mpe': $mimetype = "video/mpeg"; break; case 'avi': $mimetype = "video/x-msvideo"; break; case 'midi': $mimetype = "audio/midi"; break; case 'mid': $mimetype = "audio/mid"; break; case 'amr': $mimetype = "audio/amr"; break; default: $mimetype = "application/octet-stream"; } } //off output buffering to decrease Server usage @ob_end_clean(); if(ini_get('zlib.output_compression')){ ini_set('zlib.output_compression', 'Off'); } header('Content-Description: File Transfer'); header('Content-Type: '.$mimetype); header('Content-Disposition: attachment; filename='.$newfilename.''); header('Content-Transfer-Encoding: binary'); header("Expires: Wed, 07 May 2013 09:09:09 GMT"); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); header('Cache-Control: post-check=0, pre-check=0', false); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Pragma: no-cache'); header('Content-Length: '.$filesize); ///Will Download 1 MB in chunkwise $chunk = 1 * (1024 * 1024); $nfile = @fopen($file,"rb"); while(!feof($nfile)) { print(@fread($nfile, $chunk)); @ob_flush(); @flush(); } @fclose($filen); } ?>
<?php ///Example $file = "hello-google.pdf"; DownloadAnything($file, "forcedownload.pdf", '', false); ?>
If you find this code useful then share it with your friends or office colleagues on facebook, google + and twitter.
Gurunatha Dogi
Gurunatha Dogi is a software engineer by profession and founder of Onlinebuff.com, Onlinebuff is a tech blog which covers topics on .NET Fundamentals, Csharp, Asp.Net, PHP, MYSQL, SQL Server and lots more..... read more
Comments
By Paulb on 2016-02-27
Hi, had to change a small item in the script to work, line 67 to if(!is_readable($file)) { For some reason the @ operator does not work with this function Thanks for the script.By Julien on 2014-07-29
Brilliant ! this is exactly what i needed. Thank you.By Rahul on 2014-07-01
Awesome bro... This is what I was looking for. I tried downloading files from Ooyala service with their API but fail to successfully implement it. At the end I just passed that signed URL to this function. its downloading smoothly. Thanks a lot. Great work.Add a Comment

- By Gurunatha Dogi
- Apr 27th, 2014
- 74280
- 3
How to insert data using jQuery Ajax in PHP

- By Gurunatha Dogi
- Apr 18th, 2014
- 39465
- 3
Step by step to upload a file to ftp server using php code

- By Gurunatha Dogi
- Apr 6th, 2014
- 408299
- 3
Step by step to upload an image and store in database using php

- By Gurunatha Dogi
- May 1st, 2013
- 19235
- 3