-
-
Save AjmalPraveeN/594110c0f9ab818afa855cc84fad82c3 to your computer and use it in GitHub Desktop.
Example of using mod_xsendfile to send a file as a download.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* In your Apache conf file, set the following to enable XSendfile: | |
* | |
<Directory "/"> | |
# This should be handled by the XSendFile module, but a bug in 0.11.1 prevented it from being set properly. | |
EnableSendfile on | |
XSendFile on | |
# Absolute path to where your download files are stored. No trailing slash! | |
XSendFilePath "C:\inetpub\apacheroot\mysite\download_files" | |
</Directory> | |
*/ | |
function join_paths($paths) | |
{ | |
if (!is_array($paths)) $paths = func_get_args(); | |
foreach ($paths as $i => $part) { | |
$part = trim(preg_replace('|[\\\\/]+|', DIRECTORY_SEPARATOR, trim($part)) , DIRECTORY_SEPARATOR); | |
if (!strlen($part)) unset($paths[$i]); | |
else $paths[$i] = $part; | |
} | |
return join(DIRECTORY_SEPARATOR, $paths); | |
} | |
function can_haz_xsendfile() | |
{ | |
// This will return false if PHP is not loaded as a module (i.e. uses cgi) | |
return in_array('mod_xsendfile', apache_get_modules()); | |
} | |
function send_download_package_file($base_path, $file_path) | |
{ | |
$realpath = join_paths(DOWNLOAD_PACKAGE_BASE_ROOT, $base_path, $file_path); | |
if (file_exists($realpath)) { | |
// Fetching File | |
$mtime = ($mtime = filemtime($realpath)) ? $mtime : gmtime(); | |
$size = intval(sprintf("%u", filesize($realpath))); | |
header("Content-type: application/force-download"); | |
header('Content-Type: application/octet-stream'); | |
if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE") != false) { | |
header("Content-Disposition: attachment; filename=" . urlencode(basename($file_path)) . '; modification-date="' . date('r', $mtime) . '";'); | |
} else { | |
header("Content-Disposition: attachment; filename=\"" . basename($file_path) . '"; modification-date="' . date('r', $mtime) . '";'); | |
} | |
if (can_haz_xsendfile()) { | |
// Sending file via mod_xsendfile | |
header("X-Sendfile: " . join_paths($base_path, $file_path)); | |
} else { | |
// Sending file directly via script | |
if (intval($size + 1) > return_bytes(ini_get('memory_limit')) && intval($size * 1.5) <= 1073741824) { //Not higher than 1GB | |
// Setting memory limit | |
ini_set('memory_limit', intval($size * 1.5)); | |
} | |
@apache_setenv('no-gzip', 1); | |
@ini_set('zlib.output_compression', 0); | |
header("Content-Length: " . $size); | |
// Set the time limit based on an average D/L speed of 50kb/sec | |
set_time_limit(min(7200, // No more than 120 minutes (this is really bad, but...) | |
($size > 0) ? intval($size / 51200) + 60 // 1 minute more than what it should take to D/L at 50kb/sec | |
: 1 // Minimum of 1 second in case size is found to be 0 | |
)); | |
$chunksize = 1 * (1024 * 1024); // how many megabytes to read at a time | |
if ($size > $chunksize) { | |
// Chunking file for download | |
$handle = fopen($realpath, 'rb'); | |
$buffer = ''; | |
while (!feof($handle)) { | |
$buffer = fread($handle, $chunksize); | |
echo $buffer; | |
ob_flush(); | |
flush(); | |
} | |
fclose($handle); | |
} else { | |
// Streaming whole file for download | |
readfile($realpath); | |
} | |
} | |
return true; | |
} else { | |
// File not found! Throw error here... | |
} | |
return false; | |
} | |
// Absolute path, same as what you set for the XSendFilePath directive | |
define('DOWNLOAD_PACKAGE_BASE_ROOT', 'C:\inetpub\apacheroot\mysite\download_files'); | |
// Any intermediate path between XSendFilePath and your file. It should have neither a leading nor trailing slash | |
define('DOWNLOAD_PACKAGE_DIR', 'pdfs'); | |
if (send_download_package_file(DOWNLOAD_PACKAGE_DIR, 'some_big_file.pdf')) { | |
// Exit successfully. We could just let the script exit | |
// normally at the bottom of the page, but then blank lines | |
// after the close of the script code would potentially cause | |
// problems after the file download. | |
exit; | |
} | |
// else, raise error... | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function return_bytes($val) | |
{ | |
$val = trim($val); | |
$last = strtolower($val[strlen($val) - 1]); | |
switch ($last) { | |
// The 'G' modifier is available since PHP 5.1.0 | |
case 'g': | |
$val*= 1024; | |
case 'm': | |
$val*= 1024; | |
case 'k': | |
$val*= 1024; | |
} | |
return $val; | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment