I have a privet forms to give courses online that users can register and watching the video course Online after payment , And I need to produce the video without showing the original URL source by using this function :
// Get video view tag
function GetVideoViewTag(&$fld, $val, $tooltip = false)
{
global $Page;
if (!EmptyString($val)) {
$val = $fld->htmlDecode($val);
if ($fld->DataType == DATATYPE_BLOB) {
$wrknames = [$val];
$wrkfiles = [$val];
} elseif ($fld->UploadMultiple) {
$wrknames = explode(Config("MULTIPLE_UPLOAD_SEPARATOR"), $val);
$wrkfiles = explode(Config("MULTIPLE_UPLOAD_SEPARATOR"), $fld->htmlDecode($fld->Upload->DbValue));
} else {
$wrknames = [$val];
$wrkfiles = [$fld->htmlDecode($fld->Upload->DbValue)];
}
$multiple = (count($wrkfiles) > 1);
$href = $tooltip ? "" : $fld->HrefValue;
$isLazy = $tooltip ? false : IsLazy();
$tags = "";
$wrkcnt = 0;
foreach ($wrkfiles as $wrkfile) {
$tag = "";
if (
$Page && ($Page->TableType == "REPORT" &&
($Page->isExport("excel") && Config("USE_PHPEXCEL") ||
$Page->isExport("word") && Config("USE_PHPWORD")) ||
$Page->TableType != "REPORT" && ($Page->CustomExport == "pdf" || $Page->CustomExport == "email"))
) {
$fn = GetFileTempImage($fld, $wrkfile);
} else {
$fn = GetFileUploadUrl($fld, $wrkfile, $fld->Resize);
}
$fi = base64_encode(file_get_contents('http://localhost/onlincu/files/'.$wrkfile));
if ($href == "" && !$fld->UseColorbox) {
if ($fn != "") {
if ($isLazy) {
$tag = '<center><video style="width: 100%; height: 380px;" autoplay controls controlsList="nodownload"><source src="data:video/mp4;base64,'.$fi.'" type="video/mp4" data-src="' . $fn . '"' . $fld->viewAttributes() . '></video></center>';
} else {
$tag = '<center><video style="width: 100%; height: 380px;" autoplay controls controlsList="nodownload"><source src="data:video/mp4;base64,'.$fi.'" type="video/mp4" data-src="' . $fn . '"' . $fld->viewAttributes() . '></video></center>';
}
}
} else {
if ($fld->UploadMultiple && ContainsString($href, '%u')) {
$fld->HrefValue = str_replace('%u', GetFileUploadUrl($fld, $wrkfile), $href);
}
if ($fn != "") {
if ($isLazy) {
$tag = '<center><video style="width: 100%; height: 380px;" autoplay controls controlsList="nodownload"><source src="data:video/mp4;base64,'.$fi.'" type="video/mp4" data-src="' . $fn . '"' . $fld->viewAttributes() . '></video></center>';
} else {
$tag = '<center><video style="width: 100%; height: 380px;" autoplay controls controlsList="nodownload"><source src="data:video/mp4;base64,'.$fi.'" type="video/mp4" data-src="' . $fn . '"' . $fld->viewAttributes() . '></video></center>';
}
}
}
if ($tag != "") {
if ($multiple) {
$tags .= '<div class="p-1">' . $tag . '</div>';
} else {
$tags .= $tag;
}
}
$wrkcnt += 1;
}
if ($multiple && $tags != "") {
$tags = '<div class="d-flex flex-row">' . $tags . '</div>';
}
return $tags;
}
return "";
}
Now my function working Good even better until now , But I have read that using 'base64_encode' for videos maybe damage the original video , Well if that true What the better solution for this case ?
I appreciate your help .
I have found a solution to this it's worked for me but I wonder if this a good secure solution ?
so what I do that instead of using 'base64_encode' to encrypt my video URL source ,I tried to add this class bellow :
<?php
//VideoStream.php
class VideoStream
{
private $path = "";
private $stream = "";
private $iv = "";
private $buffer = 102400;
private $start = -1;
private $end = -1;
private $size = 0;
function __construct($filePath)
{
$this->$iv = str_repeat('z', 16);
$this->path = openssl_decrypt($filePath, "aes128", session_id(),0,$this->$iv);
}
/**
* 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, private");
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();
}
}
And my response_video.php :
<?php
//response_video.php
header("location: /onlincu/");
session_start();
// Start the session
if(isset($_GET["video_id"])&& isset($_GET["token"])){
$token_id = $_GET["token"];
$Vid_id = $_GET["video_id"];
$iv = str_repeat('z', 16);
$token = openssl_decrypt($Vid_id, "aes128", $token_id,0,$iv);
$path = openssl_encrypt("files/".$token, "aes128", session_id(),0,$iv);
require_once'VideoStream.php';
$stream = new VideoStream($path);
$stream->start();
}
?>
Finally I call my response_video.php :
<?php
//index.php
$TokenValue = 'my-token-value';
$myVideo = $Page->videofile->getViewValue() //my-Video-name-value
$iv = str_repeat('z', 16);
$path=openssl_encrypt($myVideo, "aes128", $TokenValue,0,$iv);
?>
<video oncontextmenu="return false;" id="myVideo" width="100%" height="550px" autoplay controls controlsList="nodownload">
</video>
<script>
var vid = document.getElementById("myVideo");
vid.src='response_video.php?video_id=<?= $path?>&token=<?= $TokenValue?>';
vid.type = 'video/mp4';
</script>
Now my video src look like :
src"onlincu/response_video.php?video_id=AvpAkmjPf16HapWcRKDrdhRZWFeZTBox2LDHA3zeFnk="
Related
i have use this code for download its working fine on download manager with good speed but problem with browser downloader its speed very low its 45kbps to 50kbps . can anyone help me how to set it for browser downloader also
this code
<?php
class ResumeDownload {
private $file;
private $name;
private $boundary;
private $delay = 0;
private $size = 0;
function __construct($file, $delay = 0) {
if (! is_file($file)) {
header("HTTP/1.1 400 Invalid Request");
die("<h3>File Not Found</h3>");
}
$this->size = filesize($file);
$this->file = fopen($file, "r");
$this->boundary = md5($file);
$this->delay = $delay;
$this->name = basename($file);
}
public function process() {
$ranges = NULL;
$t = 0;
if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_SERVER['HTTP_RANGE']) && $range = stristr(trim($_SERVER['HTTP_RANGE']), 'bytes=')) {
$range = substr($range, 6);
$ranges = explode(',', $range);
$t = count($ranges);
}
header("Accept-Ranges: bytes");
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: binary");
header(sprintf('Content-Disposition: attachment; filename="%s"', $this->name));
if ($t > 0) {
header("HTTP/1.1 206 Partial content");
$t === 1 ? $this->pushSingle($range) : $this->pushMulti($ranges);
} else {
header("Content-Length: " . $this->size);
$this->readFile();
}
flush();
}
private function pushSingle($range) {
$start = $end = 0;
$this->getRange($range, $start, $end);
header("Content-Length: " . ($end - $start + 1));
header(sprintf("Content-Range: bytes %d-%d/%d", $start, $end, $this->size));
fseek($this->file, $start);
$this->readBuffer($end - $start + 1);
$this->readFile();
}
private function pushMulti($ranges) {
$length = $start = $end = 0;
$output = "";
$tl = "Content-type: application/octet-stream\r\n";
$formatRange = "Content-range: bytes %d-%d/%d\r\n\r\n";
foreach ( $ranges as $range ) {
$this->getRange($range, $start, $end);
$length += strlen("\r\n--$this->boundary\r\n");
$length += strlen($tl);
$length += strlen(sprintf($formatRange, $start, $end, $this->size));
$length += $end - $start + 1;
}
$length += strlen("\r\n--$this->boundary--\r\n");
header("Content-Length: $length");
header("Content-Type: multipart/x-byteranges; boundary=$this->boundary");
foreach ( $ranges as $range ) {
$this->getRange($range, $start, $end);
echo "\r\n--$this->boundary\r\n";
echo $tl;
echo sprintf($formatRange, $start, $end, $this->size);
fseek($this->file, $start);
$this->readBuffer($end - $start + 1);
}
echo "\r\n--$this->boundary--\r\n";
}
private function getRange($range, &$start, &$end) {
list($start, $end) = explode('-', $range);
$fileSize = $this->size;
if ($start == '') {
$tmp = $end;
$end = $fileSize - 1;
$start = $fileSize - $tmp;
if ($start < 0)
$start = 0;
} else {
if ($end == '' || $end > $fileSize - 1)
$end = $fileSize - 1;
}
if ($start > $end) {
header("Status: 416 Requested range not satisfiable");
header("Content-Range: */" . $fileSize);
exit();
}
return array(
$start,
$end
);
}
private function readFile() {
while ( ! feof($this->file) ) {
echo fgets($this->file);
flush();
usleep($this->delay);
}
}
private function readBuffer($bytes, $size = 1024) {
$bytesLeft = $bytes;
while ( $bytesLeft > 0 && ! feof($this->file) ) {
$bytesLeft > $size ? $bytesRead = $size : $bytesRead = $bytesLeft;
$bytesLeft -= $bytesRead;
echo fread($this->file, $bytesRead);
flush();
usleep($this->delay);
}
}
}
$file = '/home/file.zip';
set_time_limit(0);
$download = new ResumeDownload($file, 50000); //delay about in microsecs
$download->process();
its give good speed on internet download manager when change delay microsecs . but this speed not work for browser downloader
If you don't want low download speed you should use this class like follow:
$file = '/home/file.zip';
set_time_limit(0);
$download = new ResumeDownload($file);
$download->process();
I have a website which I use to stream audio files.
Mainly, MP3 & OGG.
Since few months, I handle myself (PHP) the steaming part (before it was apache2). First I do a normal 200 OK response with sliced binary response of my multimedia audio files (for memory allocation).
It's working fine, but I got the Infinity duration on all my audio.
According to this question, I have updated yesterday the streaming part.
And now, I have one of the strangest bug I could imagine. My refactor of code works really fine with MP3 but not with OGG... Images, or zip download also works with the class above, and they both work fine as before.
Here is my Stream class.
<?php
class Stream extends Response
{
protected $filepath;
protected $delete;
protected $range = ['from' => 0, 'to' => null];
public function __construct($filePath, $delete = false, $range = NULL)
{
$this->delete = $delete;
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
$size = filesize($filePath);
$this->headers['Content-Type'] = $mimeType;
$this->headers['Content-Length'] = $size;
$this->headers['Accept-Ranges'] = 'bytes';
$this->headers['Content-Transfer-Encoding'] = 'binary';
unset($finfo, $mimeType);
$this->code = 200;
$this->range['to'] = $size - 1;
if ($range !== NULL) {
if (preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/i', $range) === false) {
$this->code = 416;
} else {
$ranges = explode(',', substr($range, 6));
foreach ($ranges as $rangee) {
$parts = explode('-', $rangee);
$this->range['from'] = intval($parts[0]);
$this->range['to'] = intval($parts[1]);
if (empty($this->range['to'])) {
$this->range['to'] = $size - 1;
}
if ($this->range['from'] > $this->range['to'] || $this->range['to'] >= $size) {
$this->code = 416;
}
}
$this->code = 206;
}
}
if ($this->code === 416) {
$this->headers = ['Content-Range' => 'bytes */{' . $size . '}'];
} elseif ($this->code === 206) {
$this->headers['Content-Range'] = 'bytes {' . $this->range['from'] . '}-{' . $this->range['to'] . '}/{' . $size . '}';
}
$this->filepath = $filePath;
}
public function show()
{
http_response_code($this->code);
foreach ($this->headers as $header => $value) {
header($header . ': ' . $value);
}
$file = fopen($this->filepath, 'r');
fseek($file, $this->range['from']);
$interval = $this->range['to'] - $this->range['from'];
$outputBufferInterval = 4 * 1000;
if ($interval < $outputBufferInterval) {
$outputBufferInterval = $interval;
}
ob_start();
while ($interval > 0) {
echo fread($file, $outputBufferInterval);
$interval -= $outputBufferInterval;
ob_flush();
}
fclose($file);
ob_end_clean();
if ($this->delete) {
unlink($this->filepath);
}
}
}
I am little confused with HTTP_RANGE.
Thank you,
i write a php download center script that make some speed limit on each user groups !
for vip group i used xsendfile and it work very nice
but in user group that must have speed limit i used fread() and force download in php :
<?php
class httpdownload {
public $data = null;
public $data_len = 0;
public $data_mod = 0;
public $data_type = 0;
public $data_section = 0; //section download
/**
* #var ObjectHandler
**/
public $handler = array('auth' => null);
public $use_resume = true;
public $use_autoexit = false;
public $use_auth = false;
public $filename = null;
public $mime = null;
public $bufsize = 2048;
public $seek_start = 0;
public $seek_end = -1;
public $newfile = null;
/**
* Total bandwidth has been used for this download
* #var int
*/
public $bandwidth = 0;
/**
* Speed limit
* #var float
*/
public $speed = 0;
/*-------------------
| Download Function |
-------------------*/
/**
* Check authentication and get seek position
* #return bool
**/
private function initialize() {
global $HTTP_SERVER_VARS;
if ($this->use_auth) //use authentication
{
if (!$this->_auth()) //no authentication
{
header('WWW-Authenticate: Basic realm="Please enter your username and password"');
header('HTTP/1.0 401 Unauthorized');
header('status: 401 Unauthorized');
if ($this->use_autoexit) exit();
return false;
}
}
if ($this->mime == null) $this->mime = "application/octet-stream"; //default mime
if (isset($_SERVER['HTTP_RANGE']) || isset($HTTP_SERVER_VARS['HTTP_RANGE']))
{
if (isset($HTTP_SERVER_VARS['HTTP_RANGE'])) $seek_range = substr($HTTP_SERVER_VARS['HTTP_RANGE'] , strlen('bytes='));
else $seek_range = substr($_SERVER['HTTP_RANGE'] , strlen('bytes='));
$range = explode('-',$seek_range);
if ($range[0] > 0)
{
$this->seek_start = intval($range[0]);
}
if ($range[1] > 0) $this->seek_end = intval($range[1]);
else $this->seek_end = -1;
if (!$this->use_resume)
{
$this->seek_start = 0;
//header("HTTP/1.0 404 Bad Request");
//header("Status: 400 Bad Request");
//exit;
//return false;
}
else
{
$this->data_section = 1;
}
}
else
{
$this->seek_start = 0;
$this->seek_end = -1;
}
return true;
}
/**
* Send download information header
**/
private function header($size,$seek_start=null,$seek_end=null) {
header('Content-type: ' . $this->mime);
header('Content-Disposition: attachment; filename="' . $this->newfile . '"');
header('Last-Modified: ' . date('D, d M Y H:i:s \G\M\T' , $this->data_mod));
if ($this->data_section && $this->use_resume)
{
header("HTTP/1.0 206 Partial Content");
header("Status: 206 Partial Content");
header('Accept-Ranges: bytes');
header("Content-Range: bytes $seek_start-$seek_end/$size");
header("Content-Length: " . ($seek_end - $seek_start + 1));
}
else
{
header("Content-Length: $size");
}
}
private function download_ex($size)
{
if (!$this->initialize()) return false;
ignore_user_abort(true);
//Use seek end here
if ($this->seek_start > ($size - 1)) $this->seek_start = 0;
if ($this->seek_end <= 0) $this->seek_end = $size - 1;
$this->header($size,$seek,$this->seek_end);
$this->data_mod = time();
return true;
}
/**
* Start download
* #return bool
**/
function download() {
if (!$this->initialize()) return false;
$seek = $this->seek_start;
$speed = $this->speed;
$bufsize = $this->bufsize;
$packet = 1;
//do some clean up
#ob_end_clean();
$old_status = ignore_user_abort(true);
#set_time_limit(0);
$this->bandwidth = 0;
$size = $this->data_len;
if ($this->data_type == 0) //download from a file
{
$size = filesize($this->data);
if ($seek > ($size - 1)) $seek = 0;
if ($this->filename == null) $this->filename = basename($this->data);
$res = fopen($this->data,'rb');
if ($seek) fseek($res , $seek);
if ($this->seek_end < $seek) $this->seek_end = $size - 1;
$this->header($size,$seek,$this->seek_end); //always use the last seek
$size = $this->seek_end - $seek + 1;
while (!(connection_aborted() || connection_status() == 1) && $size > 0)
{
if ($size < $bufsize)
{
echo fread($res , $size);
$this->bandwidth += $size;
}
else
{
echo fread($res , $bufsize);
$this->bandwidth += $bufsize;
}
$size -= $bufsize;
flush();
if ($speed > 0 && ($this->bandwidth > $speed*$packet*1024))
{
sleep(1);
$packet++;
}
}
fclose($res);
}
elseif ($this->data_type == 1) //download from a string
{
if ($seek > ($size - 1)) $seek = 0;
if ($this->seek_end < $seek) $this->seek_end = $this->data_len - 1;
$this->data = substr($this->data , $seek , $this->seek_end - $seek + 1);
if ($this->filename == null) $this->filename = time();
$size = strlen($this->data);
$this->header($this->data_len,$seek,$this->seek_end);
while (!connection_aborted() && $size > 0) {
if ($size < $bufsize)
{
$this->bandwidth += $size;
}
else
{
$this->bandwidth += $bufsize;
}
echo substr($this->data , 0 , $bufsize);
$this->data = substr($this->data , $bufsize);
$size -= $bufsize;
flush();
if ($speed > 0 && ($this->bandwidth > $speed*$packet*1024))
{
sleep(1);
$packet++;
}
}
} else if ($this->data_type == 2) {
//just send a redirect header
header('location: ' . $this->data);
}
if ($this->use_autoexit) exit();
//restore old status
ignore_user_abort($old_status);
set_time_limit(ini_get("max_execution_time"));
return true;
}
function set_byfile($dir) {
if (is_readable($dir) && is_file($dir)) {
$this->data_len = 0;
$this->data = $dir;
$this->data_type = 0;
$this->data_mod = filemtime($dir);
return true;
} else return false;
}
function set_bydata($data) {
if ($data == '') return false;
$this->data = $data;
$this->data_len = strlen($data);
$this->data_type = 1;
$this->data_mod = time();
return true;
}
function set_byurl($data) {
$this->data = $data;
$this->data_len = 0;
$this->data_type = 2;
return true;
}
function set_lastmodtime($time) {
$time = intval($time);
if ($time <= 0) $time = time();
$this->data_mod = $time;
}
/**
* Check authentication
* #return bool
**/
function _auth() {
if (!isset($_SERVER['PHP_AUTH_USER'])) return false;
if (isset($this->handler['auth']) && function_exists($this->handler['auth']))
{
return $this->handler['auth']('auth' , $_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']);
}
else return true; //you must use a handler
}
}
?>
download action :
private function downloader($filename,$type,$name,$speed_limit)
{
require_once(ROOT_PATCH . "bcore/HttpDownloader.class.php");
$object = new httpdownload();
$object->newfile = $name;
switch ($type) {
case 'resume_speed':
case 'noresume_speed':
case 'resume':
case 'noresume':
$object->set_byfile($filename);
if ($type == 'noresume' || $type == 'noresume_speed') $object->use_resume = false;
if ($type == 'resume_speed' || $type == 'noresume_speed' ) $object->speed = $speed_limit;
$object->download();
break;
case 'data':
case 'dataresume':
$data = implode('' , file($filename));
$object->set_bydata($data);
if ($_SERVER['download'] != 'dataresume') $object->use_resume = false;
$object->filename = basename($filename);
$object->download();
break;
case 'auth':
$object->set_byfile($filename);
$object->use_auth = true;
$object->handler['auth'] = "test_auth";
$object->download();
break;
case 'url':
$object->set_byurl('http://www.php.net/get/php_manual_chm.zip/from/cr.php.net/mirror');
$object->download();
break;
}
}
$type = "resume"; in above switch
but there is a problem !
NOTE : My Max internet download speed in 60kb/s
when i copy download url to IDM Add Url file downloading is very fast and good :
screen shot for copy download url to IDM Add
but when i click on url and idm get link automatically from browser file downloading is very slow with one connection !!
and after some second speed is 0 kb/s ~ 4 kb/s
what is wrong with that ?
idm get link automatically from browser
I have created a website which allows the user to zip multiple files from remote sites, combine them into a zip file, then download them. This part is working very well.
The problems I am having:
1) The zip takes too long to generate when combining multiple files
2) I cannot set the zip files name to be $name
This is what I have:
<?php
$files = unserialize($_POST['filesend']);
$name = $_POST['name'];
$zip = new ZipArchive();
$tmp_file = tempnam('.','');
$zip->open($tmp_file, ZipArchive::CREATE);
foreach($files as $file){
$download_file = file_get_contents($file);
$zip->addFromString(basename($file),$download_file);
}
$zip->close();
function downloadfile ($file, $contenttype = 'application/octet-stream') {
#error_reporting(0);
if (!file_exists($file)) {
header("HTTP/1.1 404 Not Found");
exit;
}
if (isset($_SERVER['HTTP_RANGE'])) $range = $_SERVER['HTTP_RANGE'];
else if ($apache = apache_request_headers()) {
$headers = array();
foreach ($apache as $header => $val) $headers[strtolower($header)] = $val;
if (isset($headers['range'])) $range = $headers['range'];
else $range = FALSE;
} else $range = FALSE;
$filesize = filesize($file);
if ($range) {
$partial = true;
list($param,$range) = explode('=',$range);
if (strtolower(trim($param)) != 'bytes') {
header("HTTP/1.1 400 Invalid Request");
exit;
}
$range = explode(',',$range);
$range = explode('-',$range[0]);
if (count($range) != 2) {
header("HTTP/1.1 400 Invalid Request");
exit;
}
if ($range[0] === '') {
$end = $filesize - 1;
$start = $end - intval($range[0]);
} else if ($range[1] === '') {
$start = intval($range[0]);
$end = $filesize - 1;
} else {
$start = intval($range[0]);
$end = intval($range[1]);
if ($end >= $filesize || (!$start && (!$end || $end == ($filesize - 1)))) $partial = false;
}
$length = $end - $start + 1;
} else $partial = false;
header("Content-Type: $contenttype");
header("Content-Length: $filesize");
header("Content-Disposition: attachment; filename= $name .zip");
header('Accept-Ranges: bytes');
if ($partial) {
header('HTTP/1.1 206 Partial Content');
header("Content-Range: bytes $start-$end/$filesize");
if (!$fp = fopen($file, 'r')) {
header("HTTP/1.1 500 Internal Server Error");
exit;
}
if ($start) fseek($fp,$start);
while ($length) {
$read = ($length > 8192) ? 8192 : $length;
$length -= $read;
print(fread($fp,$read));
}
fclose($fp);
} else readfile($file);
exit;
}
downloadfile ($tmp_file, $contenttype = 'application/octet-stream');
?>
Sample input:
$files = array("http://img3.wikia.nocookie.net/__cb20100520131746/logopedia/images/5/5c/Google_logo.png","http://www.logobird.com/wp-content/uploads/2011/03/new-google-chrome-logo.jpg","http://steve-lovelace.com/wordpress/wp-content/uploads/2013/06/google-logo-in-chicago-font.png","http://fc08.deviantart.net/fs70/f/2013/111/d/6/applejack_google_logo__install_guide___by_thepatrollpl-d62gui3.png","http://www.sfweekly.com/binary/fb4a/go.jpg","https://www.google.com/logos/doodles/2014/world-cup-2014-16-5975619640754176.3-hp.gif");
$name = "Google Logo's 33";
To address your two issues:
1) Slow file processing speed.
I don't know that you can help that. It is what it is.
2) Saving the name.
I have formatted this into a class, just to keep jobs separate. I find a class works better in a situation like this because it's easier to read. That being said, because each method may use the protected $filename you should copy everything here instead of breaking this code out an mixing your procedural with this class:
class DownloadFiles
{
protected $filename;
protected $Zipper;
public function Initialize($filename = false)
{
// Set the file name in the construct
$this->filename = ($filename != false)? $filename:"file".date("YmdHis");
// New ZipArchive instance
$this->Zipper = new ZipArchive();
// Drop the filename here
$this->Zipper->open($this->filename, ZipArchive::CREATE);
// Return the method for optional chaining.
return $this;
}
public function AddFiles($array = array())
{
if(!isset($this->Zipper))
return $this;
// This is just if you wanted to also use a string
// separated by commas, it will convert to array
if(!is_array($array) && strpos($array,",") !== false)
$array = explode(",",$array);
// Loop through files (as you have it already)
if(is_array($array) && !empty($array)) {
foreach($array as $url) {
// Add Contents (as you have it)
$this->Zipper->addFromString(basename($url),file_get_contents($url));
}
}
// Close zip file
$this->Zipper->close();
// Return for method chaining
return $this;
}
public function DownloadZip($contenttype = 'application/octet-stream')
{
if(!isset($this->filename))
return $this;
// Nothing really changes in this function except
// you don't need the name as an option in this function
error_reporting(0);
if (!file_exists($this->filename)) {
header("HTTP/1.1 404 Not Found");
exit;
}
$range = false;
if(isset($_SERVER['HTTP_RANGE']))
$range = $_SERVER['HTTP_RANGE'];
elseif($apache = apache_request_headers()) {
$headers = array();
foreach ($apache as $header => $val)
$headers[strtolower($header)] = $val;
$range = (isset($headers['range']))? $headers['range']:false;
}
$filesize = filesize($this->filename);
$partial = false;
if($range) {
$partial = true;
list($param,$range) = explode('=',$range);
if(strtolower(trim($param)) != 'bytes') {
header("HTTP/1.1 400 Invalid Request");
exit;
}
$range = explode(',',$range);
$range = explode('-',$range[0]);
if(count($range) != 2) {
header("HTTP/1.1 400 Invalid Request");
exit;
}
if($range[0] === '') {
$end = $filesize - 1;
$start = $end - intval($range[0]);
}
elseif($range[1] === '') {
$start = intval($range[0]);
$end = $filesize - 1;
}
else {
$start = intval($range[0]);
$end = intval($range[1]);
if($end >= $filesize || (!$start && (!$end || $end == ($filesize - 1))))
$partial = false;
}
$length = $end - $start + 1;
}
header("Content-Type: $contenttype");
header("Content-Length: $filesize");
header('Content-Disposition: attachment; filename='.$this->filename.'.zip');
header('Accept-Ranges: bytes');
if($partial) {
header('HTTP/1.1 206 Partial Content');
header("Content-Range: bytes $start-$end/$filesize");
if(!$fp = fopen($this->filename, 'r')) {
header("HTTP/1.1 500 Internal Server Error");
exit;
}
if($start)
fseek($fp,$start);
while($length) {
$read = ($length > 8192) ? 8192 : $length;
$length -= $read;
print(fread($fp,$read));
}
fclose($fp);
}
else
readfile($this->filename);
exit;
}
}
?>
To use:
$files[] = "http://img3.wikia.nocookie.net/__cb20100520131746/logopedia/images/5/5c/Google_logo.png";
$files[] = "http://www.logobird.com/wp-content/uploads/2011/03/new-google-chrome-logo.jpg";
$files[] = "http://steve-lovelace.com/wordpress/wp-content/uploads/2013/06/google-logo-in-chicago-font.png";
$files[] = "http://fc08.deviantart.net/fs70/f/2013/111/d/6/applejack_google_logo__install_guide___by_thepatrollpl-d62gui3.png";
$files[] = "http://www.sfweekly.com/binary/fb4a/go.jpg";
$files[] = "https://www.google.com/logos/doodles/2014/world-cup-2014-16-5975619640754176.3-hp.gif";
$name = "Google Logo's 33";
// Initialize
$ZDownload = new DownloadFiles();
// Run downloader
$ZDownload->Initialize($name)->AddFiles($files)->DownloadZip();
I found the following PHP script on the net which is taking a directory of images and creating thumbnails. This part works great, expect I've noticed the sorting is off. Best I can tell is it's using file names, I'd like to use creation date as I'm sorting a directory of images created from a security camera.
Any input and a bit (ok, a lot) of direction would be great as I don't have a lot of PHP experience, but can get around somewhat.
Thanks again for the help!
<html><head><title>Snapshots</title></head>
<body bgcolor='white'>
<?php
$folder = '.';
$dir = getcwd();
DirStat($folder, 0);
chdir($dir);
$FolderSize = ByteSize($FolderSize);
$FileCount=$FileCount-2;
?>
<h2 align=center><?php echo date('m/d/Y H:i:s') ." - $FileCount Snapshots - $FolderSize";?></h4>
<?php
$imagens='';
$dn = opendir('.');
while (false !== ($file = readdir($dn))) {
if ($file == '.' || $file =='..' || $file =='index.php' || $file =='Thumbs.db'){
//print "<a href=$file>$file</a><br>";
}else{
if (is_dir($file)){
print "<img src='/imagens/diretorio.png'> <a href='$file?dir=dirname(__FILE__)'>$file</a><br>";
}else{
$tamanho = filesize($file);
$m = 'bytes'; // M�ltiplo
if ($tamanho>1024) {
$tamanho=round($tamanho/1024,2);
$m = 'KB';
} elseif($tamanho > 1024*1024){
$tamanho = round(($tamanho/1024)/1024,2);
$m = 'MB';
}
$imagens .=OutputThumbnail($file, $tamanho, $m);
}
}
}
closedir($dn);
print '<br>'.$imagens;
function OutputThumbnail($image_file, $tamanho, $m)
{
if (file_exists($image_file))
{
$size = GetImageSize($image_file);
if ($size[0] <=64) {
$larg=$size[0];
}elseif ($size[0] > 64 && $size[0] <= 200) {
$larg=64;
}elseif ($size[0] > 201 && $size[0] < 400) {
$larg=128;
}elseif ($size[0] > 401) {
$larg=256;
}
if ($size[0] == 0) $size[0]=1;
$alt= ($larg * $size[1])/$size[0];
return "<a href=$image_file><img width=$larg height=$alt src=$image_file border=0
TITLE='$image_file - $larg x $alt - $tamanho $m'></a> ";
}
}
?>
<?php
function DirStat($directory) {
global $FolderCount, $FileCount, $FolderSize;
chdir($directory);
$directory = getcwd();
if($open = opendir($directory)) {
while($file = readdir($open)) {
if($file == '..' || $file == '.') continue;
if(is_file($file)) {
$FileCount++;
$FolderSize += filesize($file);
} elseif(is_dir($file)) {
$FolderCount++;
}
}
if($FolderCount > 0) {
$open2 = opendir($directory);
while($folders = readdir($open2)) {
$folder = $directory.'/'.$folders;
if($folders == '..' || $folders == '.') continue;
if(is_dir($folder)) {
DirStat($folder);
}
}
closedir($open2);
}
closedir($open);
}
}
function ByteSize($bytes) {
$size = $bytes / 1024;
if($size < 1024){
$size = number_format($size, 2);
$size .= 'KB';
} else {
if($size / 1024 < 1024) {
$size = number_format($size / 1024, 2);
$size .= 'MB';
} elseif($size / 1024 / 1024 < 1024) {
$size = number_format($size / 1024 / 1024, 2);
$size .= 'GB';
} else {
$size = number_format($size / 1024 / 1024 / 1024,2);
$size .= 'TB';
}
}
return $size;
}
?>
I have added a very dirty way of sorting (not efficient). Change below line to SORT_DESC or SORT_ASC in the code to sort descending or ascending.
arraySortByColumn($exifData, 'time', SORT_DESC);
Your script with added sorting functionality:
<html><head><title>Snapshots</title></head>
<body bgcolor='white'>
<?php
$folder = '.';
$dir = getcwd();
DirStat($folder, 0);
chdir($dir);
$FolderSize = ByteSize($FolderSize);
$FileCount=$FileCount-2;
?>
<h2 align=center><?php echo date('m/d/Y H:i:s') ." - $FileCount Snapshots - $FolderSize";?></h4>
<?php
$imagens='';
$exifData = array();
$dn = opendir('.');
while (false !== ($file = readdir($dn))) {
if ($file == '.' || $file =='..' || $file =='index.php' || $file =='Thumbs.db'){
//print "<a href=$file>$file</a><br>";
}else{
if (is_dir($file)){
print "<img src='/imagens/diretorio.png'> <a href='$file?dir=dirname(__FILE__)'>$file</a><br>";
}else{
$tamanho = filesize($file);
$datetime = #exif_read_data($file);
$m = 'bytes'; //
if ($tamanho>1024) {
$tamanho=round($tamanho/1024,2);
$m = 'KB';
} elseif($tamanho > 1024*1024){
$tamanho = round(($tamanho/1024)/1024,2);
$m = 'MB';
}
$exifData[] = array('time' => $datetime['FileDateTime'], 'file' => $file, 'tamanho' => $tamanho, 'm' => $m );
}
}
}
closedir($dn);
//change to SORT_DESC or SORT_ASC
arraySortByColumn($exifData, 'time', SORT_DESC);
foreach ($exifData as $value) {
$imagens .= OutputThumbnail($value['file'], $value['tamanho'], $value['m']);
}
print '<br>'.$imagens;
function arraySortByColumn(&$arr, $col, $dir = SORT_DESC) {
$sort_col = array();
foreach ($arr as $key => $row) {
$sort_col[$key] = $row[$col];
}
array_multisort($sort_col, $dir, $arr);
}
function OutputThumbnail($image_file, $tamanho, $m)
{
if (file_exists($image_file))
{
$size = GetImageSize($image_file);
if ($size[0] <=64) {
$larg=$size[0];
}elseif ($size[0] > 64 && $size[0] <= 200) {
$larg=64;
}elseif ($size[0] > 201 && $size[0] < 400) {
$larg=128;
}elseif ($size[0] > 401) {
$larg=256;
}
if ($size[0] == 0) $size[0]=1;
$alt= ($larg * $size[1])/$size[0];
return "<a href=$image_file><img width=$larg height=$alt src=$image_file border=0
TITLE='$image_file - $larg x $alt - $tamanho $m'></a> ";
}
}
?>
<?php
function DirStat($directory) {
global $FolderCount, $FileCount, $FolderSize;
chdir($directory);
$directory = getcwd();
if($open = opendir($directory)) {
while($file = readdir($open)) {
if($file == '..' || $file == '.') continue;
if(is_file($file)) {
$FileCount++;
$FolderSize += filesize($file);
} elseif(is_dir($file)) {
$FolderCount++;
}
}
if($FolderCount > 0) {
$open2 = opendir($directory);
while($folders = readdir($open2)) {
$folder = $directory.'/'.$folders;
if($folders == '..' || $folders == '.') continue;
if(is_dir($folder)) {
DirStat($folder);
}
}
closedir($open2);
}
closedir($open);
}
}
function ByteSize($bytes) {
$size = $bytes / 1024;
if($size < 1024){
$size = number_format($size, 2);
$size .= 'KB';
} else {
if($size / 1024 < 1024) {
$size = number_format($size / 1024, 2);
$size .= 'MB';
} elseif($size / 1024 / 1024 < 1024) {
$size = number_format($size / 1024 / 1024, 2);
$size .= 'GB';
} else {
$size = number_format($size / 1024 / 1024 / 1024,2);
$size .= 'TB';
}
}
return $size;
}
?>