9

I have an mp3 on my server (urls are just examples):

http://www.my-server.com/myaudio.mp3

I have a php script on the server at:

http://www.my-server.com/testmp3.php

Which contains the following code (which I got here):

<?
$file = "myaudio.mp3";

if (file_exists($file)) {
  header('Content-Description: File Transfer');
  header('Content-Type: application/octet-stream');
  header('Content-Disposition: attachment; filename='.basename($file));
  header('Content-Transfer-Encoding: binary');
  header('Expires: 0');
  header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  header('Pragma: public');
  header('Content-Length: ' . filesize($file));
  ob_clean();
  flush();
  readfile($file);
  exit;
}
?> 

Is this all I have to do to mimic the behavior so that both request behave the same way and return the exact same response? Or is there anything I'm missing.

I'm using some streaming code on iOS (not relevant here) and both requests stream the audio fine but I can't seek properly using the php request but I can with the mp3 request directly.

So without getting into details about the app itself I wanted to eliminate this one variable first. Is there anything I need to do to make sure that from another app's perspective these two request will return the exact same data?

Thanks for any input you can give me here.

Update

It turns out my question really should have read "how do you support seeking of an mp3 when returning from a php script?".

Community
  • 1
  • 1
nebs
  • 4,939
  • 9
  • 41
  • 70
  • Interesting question. Might be a good fit for _[Code Review](http://codereview.stackexchange.com/)_, since there isn't a specific problem. – Michael Jasper Oct 03 '11 at 17:56
  • @MichaelJasper, the specific question (as I see it) is "Does this code mimic a direct request completely?". – jball Oct 03 '11 at 17:58
  • This little PHP script is not fully implementing a HTTP request and repsonse handling. You can not expect that it handles all requests like a full blown http server. – hakre Oct 03 '11 at 17:58
  • @jball, I can see that point of view. I interpreted the question as "I think it works, but will you take a look over it just to be sure?" – Michael Jasper Oct 03 '11 at 17:59
  • @jball: Yes, technically this was my question. But now that I have the solution it turns out my question was more specific to seeking the mp3. – nebs Oct 03 '11 at 18:54
  • The example contains lots of crap. Content-Description does not exist in HTTP. Content-Type should be set to the actual media type, or none at all. The code for Content-Disposition will produce incorrect headers for many filenames. Content-Transfer-Encoding does not exist in HTTP. See also blogs.msdn.com/b/ieinternals/archive/2012/05/16/… with respect to Cache-Control. – Julian Reschke May 20 '12 at 07:50

2 Answers2

6

To support seeking, you often will have to support a range request.

From the RFC: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35

See also: Resumable downloads when using PHP to send the file?

Community
  • 1
  • 1
Brad
  • 159,648
  • 54
  • 349
  • 530
  • Thanks, this did it! I replaced my testmp3.php with the answer from your second link and seeking works now. It was related to the Range as you mentioned. – nebs Oct 03 '11 at 18:51
1

Its probably better to handle this with a .htaccess modification rather than some PHP code.
Here's a link on htaccess to get you started.

If you have a whole directory of .mp3 files that you want to appear as downloads instead of playing it in browser, you'd simply modify the .htaccess file in that folder to include

AddType application/octet-stream .mp3
Mr. Llama
  • 20,202
  • 2
  • 62
  • 115
  • This isn't really a good way to do it. There are many reasons you may want to return an MP3 with PHP, such as reading parameters out of a database to fetch the correct file. Throwing that out though, changing the type to `application/octet-stream` isn't an appropriate way to force a download. How is the receiving end supposed to definitively determine the type? The appropriate method is to set the content-disposition header. – Brad Oct 03 '11 at 19:00
  • You send a `302 Moved Temporarily` header to forward them to the proper file. Now if you're looking to prevent people from sharing the download link or require authentication to download, this isn't the way to go, but for most situations, this would work out just fine. – Mr. Llama Oct 03 '11 at 19:05