I have some problems with serving mp3's with Laravel 4.2 I have some files which should be played by flashplayer.
public function get($filename)
{
$file = new Symfony\Component\HttpFoundation\File\File(storage_path().DbConfig::get('system.upload_dir').'/'.DbConfig::get('system.upload_music').'/'.$filename);
$response = Response::make(file_get_contents(storage_path().DbConfig::get('system.upload_dir').'/'.DbConfig::get('system.upload_music').'/'.$filename));
$response->header('Content-Type', $file->getMimeType());
$response->header('Content-Length', $file->getSize());
$response->header('Content-Transfer-Encoding', '');
$response->header('Accept-Range', 'bytes');
$response->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
$response->header('Connection', 'Keep-Alive');
return $response;
}
This serves the file - if opened in chrome it lounches chrome's default player and the music plays, the same thing is when I louch it with a flashplayer.
But I'm not able to wind the record. If I serve the file with apache (instead of Laravel controller) it works fine.
I would be grateful if anyone could help me with this issue.
UPDATE
Headers when served via Laravel:
HTTP/1.1 200 OK
Date: Thu, 01 Oct 2015 18:43:59 GMT
Server: Apache/2
Cache-Control: must-revalidate, post-check=0, pre-check=0, private
Content-Transfer-Encoding:
Accept-Range: bytes
Connection: Keep-Alive, Keep-Alive
Set-Cookie: laravel_session=eyJ[...]D; expires=Thu, 01-Oct-2015 20:44:00 GMT; Max-Age=7200; path=/; httponly
Vary: Accept-Encoding,User-Agent
Keep-Alive: timeout=2, max=100
Transfer-Encoding: chunked
Content-Type: audio/mpeg
Headers when served without Laravel:
HTTP/1.1 200 OK
Date: Thu, 01 Oct 2015 18:51:16 GMT
Server: Apache/2
Last-Modified: Fri, 13 Mar 2015 04:03:23 GMT
ETag: "ead61-5112394e338c0"
Accept-Ranges: bytes
Content-Length: 961889
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: audio/mpeg
The major difference in the headers that stood out for me is the absence of
Content-Length
when using Laravel. I don't know how the flash player works, but I would venture it needs to know the length of the file to be able to seek (i.e. wind) to any position.However, the code you posted explicitly sets that header. Searching a bit, I found this Laravel issue: 2079. They suggest using the undocumented
Response::stream
to send the file contents like so:Response::stream(function() use($fileContent) { echo $fileContent; }, 200, $headers);
Here's the Symfony doc for
StreamedResponse
.Update on Response type
You are serving static files, so the appropriate response type to use is the
BinaryFileResponse
through Laravel'sResponse::download($pathToFile, $name, $headers)
.(by the way, you can use that third argument to set headers)
Update on Content-Length
The source of Symfony's
Response
class holds the key toContent-Length
getting removed:RFC 2616 does not allow both
Transfer-Encoding
andContent-Length
headers to be used and Symfony enforces this. Quote:Also, according to this SO question,
Content-Transfer-Encoding
is only used in emails.Transfer-Encoding
is used otherwise.Another thing: you used
Accept-Range
in Laravel instead ofAccept-Ranges
in Apache.Lastly, try a plain
download
response without setting any headers and see what you get. Then add more headers as needed.