sorry if this is not a new question but i'm really stuck in this problem. I'm using script below for downloading a large file like a movie, I can not let user to access direct link of the file, also I need to let user download the file in a resume and section support manner. Using this code I just have resume support, not section. I'm using Yii framework.
Please Help me on this by any solution and suggestion.
public static function downloadFile($fileLocation, $saveName = null, $maxSpeed = 100, $doStream = false){
$start = 0;
$end = -1;
$section = false;
$extension = CFileHelper::getExtension($fileLocation);
$fileName = is_null($saveName) ? basename($fileLocation) : $saveName . '.' . $extension;
/* #var $contentType string mime type for the file, if is null, it will be octet-stream */
$contentType = CFileHelper::getMimeType($fileLocation);
$contentType = is_null($contentType) ? 'application/octet-stream' : $contentType;
if(isset($_SERVER['HTTP_RANGE']))
{
$range2 = substr($_SERVER['HTTP_RANGE'], strlen('bytes='));
$range = explode('-', $range2);
if($range[0] > 0)
$start = intval($range[0]);
if($range[1] > 0)
$end = intval($range[1]);
$section = true;
}
ob_end_clean();
$old_status = ignore_user_abort(true);
set_time_limit(0);
$size = filesize($fileLocation);
if($start > ($size -1)) $start = 0;
$fp = fopen($fileLocation, 'rb');
if($start) fseek($fp, $start);
if($end < $start) $end = $size -1;
header('Content-Type: '.$contentType);
$contentDisposition = 'attachment';
if($doStream == true){
$array_listen = array('mp3','m3u','m4a','mid','ogg','ra','ram','wm',
'wav','wma','aac','3gp','avi','mov','mp4','mpeg','mpg','swf','wmv','divx','asf');
if(in_array($extension,$array_listen)){
$contentDisposition = 'inline';
}
}
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) {
$fileName= preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1);
header("Content-Disposition: $contentDisposition; filename=\"$fileName\"");
} else {
header("Content-Disposition: $contentDisposition; filename=\"$fileName\"");
}
header('Content-Disposition: ' . $contentDisposition . '; filename="' . $fileName . '"');
header('Last-Modified: ' . date('D, d M Y H:i:s \G\M\T', filemtime($fileLocation)));
if($section)
{
header("HTTP/1.0 206 Partial Content");
header("Status: 206 Partial Content");
header('Accept-Ranges: bytes');
header("Content-Range: bytes $start-$end/$size");
header("Content-Length: " . ($end - $start + 1));
}else
header('Content-Length: '.$size);
$size = $end - $start + 1;
while(!(connection_aborted() || connection_status() == 1) && !feof($fp))
{
print(fread($fp,1024*$maxSpeed));
flush();
ob_flush();
sleep(1);
}
fclose($fp);
ignore_user_abort($old_status);
set_time_limit(ini_get('max_execution_time'));
}
If you are using apache and able to install mods to it, you can use mod_xsendfile module. It supports partial downloads, cashing and other cool things.
Simple demo: Send Files Faster & Better with PHP & X-Sendfile
Related
i trying to write an script for transferring data with limit with restrictions for premium or free or low loading fast loading and etc
i found this code in internet
date_default_timezone_set('GMT');
//1- file we want to serve :
$data_file = "movie.mp4";
$data_size = filesize($data_file); //Size is not zero base
$mime = 'application/otect-stream'; //Mime type of file. to begin download its better to use this.
$filename = basename($data_file); //Name of file, no path included
//2- Check for request, is the client support this method?
if (isset($_SERVER['HTTP_RANGE']) || isset($HTTP_SERVER_VARS['HTTP_RANGE'])) {
$ranges_str = (isset($_SERVER['HTTP_RANGE']))?
$_SERVER['HTTP_RANGE']:$HTTP_SERVER_VARS['HTTP_RANGE'];
$ranges_arr = explode('-', substr($ranges_str, strlen('bytes=')));
//Now its time to check the ranges
if ((intval($ranges_arr[0]) >= intval($ranges_arr[1]) && $ranges_arr[1] != "" &&
$ranges_arr[0] != "" )
|| ($ranges_arr[1] == "" && $ranges_arr[0] == "")
) {
//Just serve the file normally request is not valid :(
$ranges_arr[0] = 0;
$ranges_arr[1] = $data_size - 1;
}
} else { //The client dose not request HTTP_RANGE so just use the entire file
$ranges_arr[0] = 0;
$ranges_arr[1] = $data_size - 1;
}
//Now its time to serve file
$file = fopen($data_file, 'rb');
$start = $stop = 0;
if ($ranges_arr[0] === "") { //No first range in array
//Last n1 byte
$stop = $data_size - 1;
$start = $data_size - intval($ranges_arr[1]);
} elseif ($ranges_arr[1] === "") { //No last
//first n0 byte
$start = intval($ranges_arr[0]);
$stop = $data_size - 1;
} else {
// n0 to n1
$stop = intval($ranges_arr[1]);
$start = intval($ranges_arr[0]);
}
//Make sure the range is correct by checking the file
fseek($file, $start, SEEK_SET);
$start = ftell($file);
fseek($file, $stop, SEEK_SET);
$stop = ftell($file);
$data_len = $stop - $start;
//Lets send headers
if (isset($_SERVER['HTTP_RANGE']) || isset($HTTP_SERVER_VARS['HTTP_RANGE'])) {
header('HTTP/1.0 206 Partial Content');
header('Status: 206 Partial Content');
}
header('Accept-Ranges: bytes');
header('Content-type: ' . $mime);
header('Content-Disposition: attachment; filename="' . $filename . '"');
header("Content-Range: bytes $start-$stop/" . $data_size );
header("Content-Length: " . ($data_len + 1));
//Finally serve data and done ~!
fseek($file, $start, SEEK_SET);
$bufsize = 50;
ignore_user_abort(true);
#set_time_limit(0);
while (!(connection_aborted() || connection_status() == 1) && $data_len > 0) {
echo fread($file, $bufsize);
$data_len -= $bufsize;
usleep(1000);
flush();
}
fclose($file);
i have a problem with script execution
t want to create connection limit when i download file with idm
i tried to count execution script run with fopen in text file and stop script run with exit function and also try class property but doesn't work
i realized everytime idm send request for another connection whole script execute from the begin
this will work but only for the first time, when i click stop and resume again a problem arises
$file=fopen('text.txt','wr');
//..... code
if ($count < 6){
exit();
}
does anyone have a solution for this problem
I spent a week to find right answer on this question. 'Right' I mean absolutely conform to existing web-standards, reliable and performance effective. Finally, I've found the solution.
All what I've found on StackOverflow (Downloading large files reliably in PHP, How to download large files through PHP script) is not works for me:
Both solutions are not support of range requests. It makes them not working for video and audio streaming and download resuming;
All examples have nothing about caching and performance;
PHP 7.0 code tested with desktop versions of Chrome, Safari, Opera and Firefox. Vivaldi test was not successful.
const STDOUT_CHUNK_SIZE = 128 * 1024; // Buffer size to send data to browser. MUST be less then 1/3 of PHP memory size
const CACHE_EXP_SEC = 1800; // Cache expire time is 30 min.
$fileName = "large_video.mp4";
$contentSize = filesize($fileName);
$isAttachment = false; // false allows to use a file as inline element of web page
// Parse range request. Browser asks for part of file
if (isset($_SERVER["HTTP_RANGE"])) {
list($units, $range) = explode("=", $_SERVER["HTTP_RANGE"], 2);
if ($units !== "bytes") {
http_response_code(416); // Requested Range Not Satisfiable
exit;
}
$range = explode(",", $range, 2)[0]; // Get only first range. You can improve this ;)
list($from, $to) = explode("-", $range, 2);
$to = empty($to) ? ($contentSize - 1) : min(abs((int)$to), ($contentSize - 1));
$from = (empty($from) || $to < abs((int)$from)) ? 0 : max(abs((int)$from), 0);
}
else {
// Request for whole content
$from = 0;
$to = $contentSize - 1;
}
// Set response headers
if ($from > 0 || $to < ($contentSize - 1))
{
http_response_code(206); // Partial Content
header("Content-Type: video/mp4"));
header("Content-Range: bytes $from-$to/$contentSize");
header("Content-Length: " . ($from - $to + 1));
}
else {
$etag = md5($file); // Content is immutable but file name can be changed
if (isset($_SERVER["HTTP_IF_NONE_MATCH"]) && trim($_SERVER["HTTP_IF_NONE_MATCH"]) === $etag) {
http_response_code(304); // Not Modified
setCacheHeaders($etag);
exit;
}
http_response_code(200); // Ok
header("Content-Type: video/mp4"));
header("Content-Length: $contentSize");
if ($isAttachment) header("Content-Disposition: attachment; filename=\"$fileName\"");
else header("Content-Disposition: inline");
header("Accept-Ranges: bytes");
setCacheHeaders($etag);
}
// Send response to client
if ($file = fopen($fileName, "rb")) {
fseek($file, $from);
$counter = $from;
set_time_limit(0);
while (!feof($file) && $counter <= $to) {
$bytesToRead = STDOUT_CHUNK_SIZE;
if ($counter + $bytesToRead > $to) $bytesToRead = $to - $counter + 1;
$data = fread($file, $bytesToRead);
$counter += $bytesToRead;
echo $data;
flush();
}
fclose($file);
function setCacheHeaders(string $etag, bool $cacheEnabled = true, bool $public = true)
{
if ($cacheEnabled) {
header("ETag: $etag");
$scope = $public ? "public" : "private";
$sec = CACHE_EXP_SEC;
$age = ($sec >= 0) ? ", max-age=$sec, s-maxage=$sec" : "";
header("Cache-Control: $scope$age, no-transform");
}
else header("Cache-Control: no-cache, no-store, must-revalidate");
}
I have a 200MB file that I want to give to a user via download. However, since we want the user to only download this file once, we are doing this:
echo file_get_contents('http://some.secret.location.com/secretfolder/the_file.tar.gz');
to force a download. However, this means that the whole file has to be loaded in memory, which usually doesn't work. How can we stream this file to them, at some kb per chunk?
Try something like this (source http://teddy.fr/2007/11/28/how-serve-big-files-through-php/):
<?php
define('CHUNK_SIZE', 1024*1024); // Size (in bytes) of tiles chunk
// Read a file and display its content chunk by chunk
function readfile_chunked($filename, $retbytes = TRUE) {
$buffer = '';
$cnt = 0;
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
$buffer = fread($handle, CHUNK_SIZE);
echo $buffer;
ob_flush();
flush();
if ($retbytes) {
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes && $status) {
return $cnt; // return num. bytes delivered like readfile() does.
}
return $status;
}
// Here goes your code for checking that the user is logged in
// ...
// ...
if ($logged_in) {
$filename = 'path/to/your/file';
$mimetype = 'mime/type';
header('Content-Type: '.$mimetype );
readfile_chunked($filename);
} else {
echo 'Tabatha says you haven\'t paid.';
}
?>
Use fpassthru(). As the name suggests, it doesn't read the entire file into memory prior to sending it, rather it outputs it straight to the client.
Modified from the example in the manual:
<?php
// the file you want to send
$path = "path/to/file";
// the file name of the download, change this if needed
$public_name = basename($path);
// get the file's mime type to send the correct content type header
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $path);
// send the headers
header("Content-Disposition: attachment; filename=$public_name;");
header("Content-Type: $mime_type");
header('Content-Length: ' . filesize($path));
// stream the file
$fp = fopen($path, 'rb');
fpassthru($fp);
exit;
If you would rather stream the content directly to the browser rather than a download (and if the content type is supported by the browser, such as video, audio, pdf etc) then remove the Content-Disposition header.
Take a look at the example from the manual page of fsockopen():
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
This will connect to www.example.com, send a request then get and echo the response in 128 byte chunks. You may want to make it more than 128 bytes.
I found this method in http://codesamplez.com/programming/php-html5-video-streaming-tutorial
And it works very well for me
<?php
class VideoStream
{
private $path = "";
private $stream = "";
private $buffer = 102400;
private $start = -1;
private $end = -1;
private $size = 0;
function __construct($filePath)
{
$this->path = $filePath;
}
/**
* Open stream
*/
private function open()
{
if (!($this->stream = fopen($this->path, 'rb'))) {
die('Could not open stream for reading');
}
}
/**
* Set proper header to serve the video content
*/
private function setHeader()
{
ob_get_clean();
header("Content-Type: video/mp4");
header("Cache-Control: max-age=2592000, public");
header("Expires: ".gmdate('D, d M Y H:i:s', time()+2592000) . ' GMT');
header("Last-Modified: ".gmdate('D, d M Y H:i:s', #filemtime($this->path)) . ' GMT' );
$this->start = 0;
$this->size = filesize($this->path);
$this->end = $this->size - 1;
header("Accept-Ranges: 0-".$this->end);
if (isset($_SERVER['HTTP_RANGE'])) {
$c_start = $this->start;
$c_end = $this->end;
list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
if (strpos($range, ',') !== false) {
header('HTTP/1.1 416 Requested Range Not Satisfiable');
header("Content-Range: bytes $this->start-$this->end/$this->size");
exit;
}
if ($range == '-') {
$c_start = $this->size - substr($range, 1);
}else{
$range = explode('-', $range);
$c_start = $range[0];
$c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end;
}
$c_end = ($c_end > $this->end) ? $this->end : $c_end;
if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) {
header('HTTP/1.1 416 Requested Range Not Satisfiable');
header("Content-Range: bytes $this->start-$this->end/$this->size");
exit;
}
$this->start = $c_start;
$this->end = $c_end;
$length = $this->end - $this->start + 1;
fseek($this->stream, $this->start);
header('HTTP/1.1 206 Partial Content');
header("Content-Length: ".$length);
header("Content-Range: bytes $this->start-$this->end/".$this->size);
}
else
{
header("Content-Length: ".$this->size);
}
}
/**
* close curretly opened stream
*/
private function end()
{
fclose($this->stream);
exit;
}
/**
* perform the streaming of calculated range
*/
private function stream()
{
$i = $this->start;
set_time_limit(0);
while(!feof($this->stream) && $i <= $this->end) {
$bytesToRead = $this->buffer;
if(($i+$bytesToRead) > $this->end) {
$bytesToRead = $this->end - $i + 1;
}
$data = fread($this->stream, $bytesToRead);
echo $data;
flush();
$i += $bytesToRead;
}
}
/**
* Start streaming video content
*/
function start()
{
$this->open();
$this->setHeader();
$this->stream();
$this->end();
}
}
To use this class, you will have to write simple code like as below:
$stream = new VideoStream($filePath);
$stream->start();
I ran into this problem as well using readfile() to force a download. The memory problem lies not within readfile, rather with ouput buffering.
Just make sure you switch off output buffering before readfile, and the problem should be fixed.
if (ob_get_level()) ob_end_clean();
readfile($yourfile);
Works for files with a size much larger than the allocated memory limit.
I am making a zend project that has a file upload functionality and the client wanted to encrypt and upload the files without their extension. I did that perfectly by using the following code :
$upload = new Zend_File_Transfer_Adapter_Http ();
$salt = $upload->getHash('md5', 'file_name');
$upload->addFilter('Rename', array('target' => APPLICATION_PATH . '/../../uploads/presentations/'.$salt));
$upload->addFilter('Encrypt', array('adapter' => 'mcrypt', 'key' => $constants->encryption_key));
$upload->receive ();
This is working fine now I'm just downloading the file with the following code
$filename = 'example_presentation_file.ppt'; //original name in db. by the way this coming from database
$hash = '85be69db87a43265a44be1482cc6d819'; //changed file name when uploaded with this
$mime = 'application/octet-stream';
$file_path = APPLICATION_PATH . '/../../uploads/presentations/'.$hash;
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
$size = filesize($file_path);
if(isset($_SERVER['HTTP_RANGE']))
{
list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2);
list($range) = explode(",",$range,2);
list($range, $range_end) = explode("-", $range);
$range = intval($range);
if(!$range_end) {
$range_end = $size-1;
}
else {
$range_end = intval($range_end);
}
$new_length = $range_end-$range+1;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range-$range_end/$size");
}
else {
$new_length = $size;
header("Content-Length: ".$size);
}
#ob_end_clean();
$speed = false;
$chunksize = ($speed?($speed * 1024):(1024 * 1024)) ;
$bytes_send = 0;
$buffer = "";
if ($file = fopen($file_path, 'r')) {
if(isset($_SERVER['HTTP_RANGE'])) {
fseek($file, $range);
}
while(!feof($file) && (!connection_aborted()) && ($bytes_send<$new_length)) {
$buffer = fread($file, $chunksize);
print($buffer);
flush();
if($speed) {
if($type!=2) sleep(1);
}
$bytes_send += strlen($buffer);
}
fclose($file);
}
This code is working very fine and downloading the file but when I open that file in powerpoint, it doesn't open it and displays an error.
The point is that, If i disable the file encryption, I opens very good but it is necessary. I just wanted to know that how to decrypt the file in run time (just when user downloads it not forever).
Thanks.
I suggest the following workflow:
Temporary decrypt the encrypted file and save it somewhere
Send this decrypted file to the client
Remove decrypted file from the file system
Example:
<?php
/* ... */
$options = array(
'adapter' => 'mcrypt',
'key' => $constants->encryption_key);
$decrypt = new Zend_Filter_File_Decrypt($options);
// temp. decrypt file and save it on the disc
$decrypted_file_path = APPLICATION_PATH . '/../../uploads/presentations/'. $filename;
$decrypt->setFilename($decrypted_file_path);
// encrypted file location
$decrypt->filter($file_path);
/* your code: Send $decrypted_file_path to the client */
// remove decrypted file
unlink($decrypted_file_path);
I've searched many topics and posts and made my own downloading snippet with 2 functions as below!
Download starts with no problem, custom errors are shown when user hasn't enough credit, all things are right but the resume! I thought it maybe Headers, but I didn't miss them.
I read many posts on stackoverflow too.
Helps needed!
function readfile_chunked($filename, $size = '', $uid, $pid, $retbytes = TRUE)
{
global $each_download;
$chunk_size = 1024*1024;
$buffer = '';
$cnt =0;
$handle = fopen($filename, 'rb');
if ($handle === false)
{
return false;
}
//check if http_range is sent by browser (or download manager)
if(isset($_SERVER['HTTP_RANGE']))
{
list($a, $range)=explode("=",$_SERVER['HTTP_RANGE']);
str_replace($range, "-", $range);
$size2=$size-1;
$new_length=$size2-$range;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range$size2/$size");
fseek($fp,$range);
}
else
{
if(get_user_meta($uid, 'revo_dropped', true) != $pid)
{
update_user_meta($uid, 'dropped', $pid);
update_user_meta($uid, 'credits', get_user_meta($uid, 'credits', true)-$each_download);
}
$size2 = $size-1;
header("Content-Range: bytes 0-$size2/$size");
header("Content-Length: ".$size);
}
while (!feof($handle) && connection_status()==0)
{
#set_time_limit(0);
$buffer = fread($handle, $chunk_size);
echo $buffer;
ob_flush();
flush();
if ($retbytes)
{
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes && $status)
{
return $cnt;
}
return $status;
}
function save_file()
{
global $wpdb;
global $uid;
global $each_download;
$hash = #$_GET["download"];
ini_set('zlib.output_compression', 'Off');
set_time_limit(0);
session_cache_limiter('none');
set_magic_quotes_runtime(0);
if(preg_match('/^[a-z0-9]{32}$/i',$hash))
{
if($row = $wpdb->get_row("SELECT * FROM wp_dlurl WHERE hash = '{$hash}'",ARRAY_A))
{
if(is_user_logged_in())
{
if($row['price'] != 0)
$each_download = $row['price'];
if(get_user_meta($uid, 'credits', true) >= $each_download)
{
$parts = pathinfo($row['url']);
$url = $parts['dirname'] . '/' . $parts['basename'];//urlencode($parts['basename']);
$file = pathinfo($row['filename']);
$ext = $file['extension'];
/* List of File Types */
$fileTypes['swf'] = 'application/x-shockwave-flash';
$fileTypes['pdf'] = 'application/pdf';
$fileTypes['exe'] = 'application/octet-stream';
$fileTypes['zip'] = 'application/zip';
$fileTypes['doc'] = 'application/msword';
$fileTypes['xls'] = 'application/vnd.ms-excel';
$fileTypes['ppt'] = 'application/vnd.ms-powerpoint';
$fileTypes['gif'] = 'image/gif';
$fileTypes['png'] = 'image/png';
$fileTypes['jpeg'] = 'image/jpg';
$fileTypes['jpg'] = 'image/jpg';
$fileTypes['rar'] = 'application/rar';
$fileTypes['ra'] = 'audio/x-pn-realaudio';
$fileTypes['ram'] = 'audio/x-pn-realaudio';
$fileTypes['ogg'] = 'audio/x-pn-realaudio';
$fileTypes['wav'] = 'video/x-msvideo';
$fileTypes['wmv'] = 'video/x-msvideo';
$fileTypes['avi'] = 'video/x-msvideo';
$fileTypes['asf'] = 'video/x-msvideo';
$fileTypes['divx'] = 'video/x-msvideo';
$fileTypes['mp3'] = 'audio/mpeg';
$fileTypes['mp4'] = 'audio/mpeg';
$fileTypes['mpeg'] = 'video/mpeg';
$fileTypes['mpg'] = 'video/mpeg';
$fileTypes['mpe'] = 'video/mpeg';
$fileTypes['mov'] = 'video/quicktime';
$fileTypes['swf'] = 'video/quicktime';
$fileTypes['3gp'] = 'video/quicktime';
$fileTypes['m4a'] = 'video/quicktime';
$fileTypes['aac'] = 'video/quicktime';
$fileTypes['m3u'] = 'video/quicktime';
$contentType = $fileTypes[$ext];
//ob_end_clean();
ob_start();
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Robots: none");
header("Content-Type: ".$contentType."");
header("Content-Description: File Transfer");
$new_name = $row['filename'];//rand(1000,999999).".".$ext;
$contentDisposition = 'attachment';
if(strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
{
$new_name = preg_replace('/\./', '%2e', $new_name, substr_count($new_name,'.') - 1);
}
$new_name = urlencode($new_name);
//#ob_end_clean();
header("Content-Disposition: ".$contentDisposition."; filename=\"".$new_name."\";");
header("Content-Transfer-Encoding: binary");
header("Accept-Ranges: bytes");
$size = $row['size'];
$thefile = $url;
$urlparsed = parse_url($thefile); // urlllllllllllll
$isURI = array_key_exists('scheme', $urlparsed);
$localURI = (bool) strstr($thefile, get_bloginfo('wpurl'));
$patterns = array( '|^'. get_bloginfo('wpurl') . '/' . '|');
$path = preg_replace( $patterns, '', $thefile );
// this is joining the ABSPATH constant, changing any slashes to local filesystem slashes, and then finally getting the real path.
$thefile = str_replace( '/', DIRECTORY_SEPARATOR, path_join( ABSPATH, $path ) );
///////////////////////////////////
if($size == 0)
{
showMessage('Size 0');
}
if (isset($size) && $size > 0)
{
//header("Content-Length: ".$size);
#readfile_chunked($thefile, $size, $uid, $pid);
}
///////////////////////////////////
exit;
}
else
showMessage("buy credit");
}
else
showMessage("login");
}
else
{
wp_redirect(get_bloginfo('url'));
exit;
}
}
else
{
wp_redirect(get_bloginfo('url'));
exit;
}
}
This script might help you out:
<?php
/**
* Copyright 2012 Armand Niculescu - media-division.com
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// get the file request, throw error if nothing supplied
// hide notices
#ini_set('error_reporting', E_ALL & ~ E_NOTICE);
//- turn off compression on the server
#apache_setenv('no-gzip', 1);
#ini_set('zlib.output_compression', 'Off');
if(!isset($_REQUEST['file']) || empty($_REQUEST['file']))
{
header("HTTP/1.0 400 Bad Request");
exit;
}
// sanitize the file request, keep just the name and extension
// also, replaces the file location with a preset one ('./myfiles/' in this example)
$file_path = $_REQUEST['file'];
$path_parts = pathinfo($file_path);
$file_name = $path_parts['basename'];
$file_ext = $path_parts['extension'];
$file_path = './myfiles/' . $file_name;
// allow a file to be streamed instead of sent as an attachment
$is_attachment = isset($_REQUEST['stream']) ? false : true;
// make sure the file exists
if (is_file($file_path))
{
$file_size = filesize($file_path);
$file = #fopen($file_path,"rb");
if ($file)
{
// set the headers, prevent caching
header("Pragma: public");
header("Expires: -1");
header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
header("Content-Disposition: attachment; filename=\"$file_name\"");
// set appropriate headers for attachment or streamed file
if ($is_attachment)
header("Content-Disposition: attachment; filename=\"$file_name\"");
else
header('Content-Disposition: inline;');
// set the mime type based on extension, add yours if needed.
$ctype_default = "application/octet-stream";
$content_types = array(
"exe" =--> "application/octet-stream",
"zip" => "application/zip",
"mp3" => "audio/mpeg",
"mpg" => "video/mpeg",
"avi" => "video/x-msvideo",
);
$ctype = isset($content_types[$file_ext]) ? $content_types[$file_ext] : $ctype_default;
header("Content-Type: " . $ctype);
//check if http_range is sent by browser (or download manager)
if(isset($_SERVER['HTTP_RANGE']))
{
list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
if ($size_unit == 'bytes')
{
//multiple ranges could be specified at the same time, but for simplicity only serve the first range
//http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra_ranges) = explode(',', $range_orig, 2);
}
else
{
$range = '';
header('HTTP/1.1 416 Requested Range Not Satisfiable');
exit;
}
}
else
{
$range = '';
}
//figure out download piece from range (if set)
list($seek_start, $seek_end) = explode('-', $range, 2);
//set start and end based on range (if set), else set defaults
//also check for invalid ranges.
$seek_end = (empty($seek_end)) ? ($file_size - 1) : min(abs(intval($seek_end)),($file_size - 1));
$seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)),0);
//Only send partial content header if downloading a piece of the file (IE workaround)
if ($seek_start > 0 || $seek_end < ($file_size - 1))
{
header('HTTP/1.1 206 Partial Content');
header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$file_size);
header('Content-Length: '.($seek_end - $seek_start + 1));
}
else
header("Content-Length: $file_size");
header('Accept-Ranges: bytes');
set_time_limit(0);
fseek($file, $seek_start);
while(!feof($file))
{
print(#fread($file, 1024*8));
ob_flush();
flush();
if (connection_status()!=0)
{
#fclose($file);
exit;
}
}
// file save was a success
#fclose($file);
exit;
}
else
{
// file couldn't be opened
header("HTTP/1.0 500 Internal Server Error");
exit;
}
}
else
{
// file does not exist
header("HTTP/1.0 404 Not Found");
exit;
}
Taken from:
http://www.richnetapps.com/php-download-script-with-resume-option/