I want to allow the serving of binary files with some sort of access control. Since the control is rather complex, I cannot simply let Apache serve the files, I have to serve them via PHP, using my Zend Framework 2 app. The action goes like this:
public function sendAction() {
$filename = /* database action */;
$size = filesize($filename);
$response = $this->getResponse();
if($this->getRequest()->getHeaders()->has('Range')) {
list($unit, $range) = explode('=', $this->getRequest()->getHeaders()->get('Range')->toString());
$ranges = explode(',', $range);
$ranges = explode('-', $ranges[0]);
$start = (int)$ranges[0];
$end = (int)(isset($ranges[1]) ? $ranges[1] : $size - 1);
$length = $start - $end;
$response->getHeaders()->addHeaders(array('Content-Type' => 'audio/mpeg', 'Accept-Ranges' => 'bytes', 'Content-Length' => $length - 1));
$response->setStatusCode(206);
$f = fopen($filename, 'r');
if($start) fseek($f, $start);
$out = '';
while($length) {
$read = ($length > 8192) ? 8192 : $length;
$length -= $read;
$out .= fread($fp,$read);
}
fclose($f);
$response->setContent($out);
} else {
$response
->setContent(file_get_contents($filename))
->getHeaders()->addHeaders(array('Content-Type' => 'audio/mpeg', 'Accept-Ranges' => 'bytes'));
}
return $this->getResponse();
}
Well for one, I am sure this is very inefficient as the files are always loaded into the RAM entirely for this before being served.
However, this doesn't seem to work. When I try to access the file, I get the correct audio/mpeg
player in Chrome, but then the browser cancels the requests and stops. I can't play the audio at all.
I could not find any hint on the web on how to implement a 206 response in Zend 2 the correct way, perhaps someone can help me here.
You should use stream.
Sample code from my application
public function documentAction()
{
$name = $this->params('name');
try {
if (!$this->getServiceLocator()->get('AuthStorage')->hasIdentity()) {
throw new \Exception('You must login.');
}
$file = getcwd().'/data/uploads/'.pathinfo($name)['basename'];
if (file_exists($file)) {
$response = new \Zend\Http\Response\Stream();
$headers = new \Zend\Http\Headers();
$headers->addHeaderLine('Content-type', 'application/pdf');
$response->setHeaders($headers);
$response->setStream(fopen($file, 'r'));
return $response;
} else {
throw new \Exception('File not exist');
}
}
catch (\Exception $e) {
$this->flashMessenger()->setNamespace('error')->addMessage('404');
return $this->redirect()->toUrl('/');
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With