Skip to content

Instantly share code, notes, and snippets.

@itskenny0
Created May 29, 2016 12:19
Show Gist options
  • Save itskenny0/5a2588a43aa8a5452dde83ea3cbc9ae5 to your computer and use it in GitHub Desktop.
Save itskenny0/5a2588a43aa8a5452dde83ea3cbc9ae5 to your computer and use it in GitHub Desktop.
<?php
/**
* FileServe
*
* Class that serves a file from disk to a client.
*
* @package FileServe
* @author Kenny <[email protected]>
* @license The Unlicense (http://unlicense.org)
*/
class FileServe {
private $stream;
private $filename;
const FILE_BUFFER = 8192; //buffer 8192 KByte of the file on every read. You might want to play with this value.
const CONTENT_TYPE = "application/octet-stream";
/**
** Constructor
*
* Called when instantiating the class.
*
* @param str $filename Filename of the file to be read.
* @throws Exception if input file doesn't exist or cannot be read
*/
public function __construct($filename) {
if(!file_exists($filename)) throw new Exception("The given input file does not exist.");
$this->stream = fopen($filename, 'r');
$this->filename = basename($filename);
if($this->stream === false) throw new Exception("Could not read file. Please check permissions.");
else return true;
}
/**
* Serve file
*
* Starts serving the file to the client.
*
* @throws Exception if stream dead or file empty
* @param $throttle (optional) Defines amount of throttle in the transmission in nanoseconds. Defaults to no throttle.
* @return true after transmission completed
*/
public function serve($throttle = 0) {
if(!is_resource($this->stream)) throw new Exception("The stream has gone away. This should not occur.");
if(feof($this->stream)) throw new Exception("The file is empty.");
header('Content-Type: ' . self::CONTENT_TYPE);
header('Content-Transfer-Encoding: Binary');
header('Content-disposition: attachment: filename="' . $this->filename . '"');
do {
echo $fileChunk;
if($throttle > 0) usleep($throttle);
} while (false !== ($fileChunk = $this->readChunk()));
return true;
}
/**
* Get next chunk
*
* Gets a chunk from the file and returns it.
*
* @return str chunk if chunk read correctly, false if file pointer is EOF
*/
private function readChunk() {
if(feof($this->stream)) return false;
$chunk = fread($this->stream, self::FILE_BUFFER);
return $chunk;
}
}
/* Example usage */
$fSrv = new FileServe("debian-8.4.0-amd64-netinst.iso");
$fSrv->serve();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment