I have been asked to create a php 5 script that will download a mp3 file and ask the user where to save it. This script is not working: the browser spends a long time before displaying "Waiting for file ....". Finally the browser displays a message saying that it cannot display the page. Here is the code I have been using:

<?php
$file = 'Oregon-AM.mp3';
$mime_type = "audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3";

if(file_exists($file)){
header('Content-type: {$mime_type}');
header('Content-length: ' . filesize($file));
header('Content-Disposition: filename="' . $filename);
header('X-Pad: avoid browser bug');
header('Cache-Control: no-cache');
readfile($file);
}else{
header("HTTP/1.0 404 Not Found");
}
?>

Suggestions are welcomed...

Todd

    header("Content-Disposition: attachment;filename=$teh_filename");

    I would imagine, but don't know, that sending a disposition header without actually giving the disposition might cause an error such as the one you describe.

      I wouldn't be surprise if the behavior even varied from one browser to the next, since this:

      Content-Disposition: filename="Oregon-AM.mp3

      is not a valid header for two reasons (missing disposition type and ending quote).

      I would also recommend adding the quotes that dalecosp omitted from his example above to ensure the file name isn't misunderstood (in case it later has a space in it).

      EDIT: Also, if you really want to try to force the browser to open a "Save As..." type dialog, note you could change the content type to "application/octet-stream" instead.

        This works in IE 8:

        <?php
        $file = 'test_mp3.mp3';

        if (file_exists($file)) {
        header('Content-Description: File Transfer');
        //header('Content-Type: application/octet-stream');

        header('Content-Type: audio/mpeg');
        header('Content-Disposition: attachment; filename="'. basename($file) . '"');
        header('Content-Transfer-Encoding: binary');

        header('Content-Length: ' . filesize($file));
        if (ob_get_level()) ob_end_clean(); // make sure buffering is off
        readfile($file);
        exit;
        }else{
        header("HTTP/1.0 404 Not Found");
        }
        ?>

        However I have several questions:

        *** Is there a way to examine the header before executing the readfile()?

        *** When the file is not found, the above code does not display an error screen. Is there a better way to handle the error?

        *** As suspected, IE, Safari and Firefox give the User a choice of playing or saving the file. Chrome does not. Is there a tweak for Chrome so that it will ask?

        Many thanks for helping me sort this out.

        Todd

          rtcary;11019437 wrote:

          Is there a way to examine the header before executing the readfile()?

          What do you mean "examine"? You can always test your code by viewing the headers that actually get sent by your webserver when you access the script in your browser. (At least, you can if your browser supports viewing raw HTTP responses - most halfway decent browsers do.)

          rtcary;11019437 wrote:

          When the file is not found, the above code does not display an error screen. Is there a better way to handle the error?

          What do you mean by "not found"? You must not mean "the file doesn't exist", since your code would result in a 404 error in that case. If you can describe the exact error scenario you're trying to handle, the answer is most likely yes, there's a good way to handle that condition gracefully.

          rtcary;11019437 wrote:

          As suspected, IE, Safari and Firefox give the User a choice of playing or saving the file. Chrome does not. Is there a tweak for Chrome so that it will ask?

          Not sure what you mean by "as suspected", but... have you tried switching to the "application/octet-stream" content type header (e.g. the one that is currently commented out)?

          EDIT: By the way... when posting code, please use the board's [noparse]

          ..

          [/noparse] bbcode tags as they make your code much easier to read and analyze.

            Thank you for your detailed response and I apologize for not being clearer in my questions (maybe that is why I was put into bonehead English at Stanford :-) ).

            I did some research into Chrome and why there is not a choice: it is purposely done that way so that the User knows where the files are located and all the User needs to do is click on the item in the lower left. Apparently some people do not like this, however I understand the development teams reasoning; it just that the person who asked for my help is working with vision impaired users and uses IE to make it easier.

            Concerning how to handle a "File does not exist condition", I usually return a page with that error message, however the code above is something I found on the Internet and hoped that it would cause a 404 page to appear; it does not.

            Many thanks for your help AND patience...

            Todd

              rtcary;11019445 wrote:

              I did some research into Chrome and why there is not a choice: it is purposely done that way so that the User knows where the files are located and all the User needs to do is click on the item in the lower left.

              Oh! I didn't understand that the file was still being downloaded - I thought you were claiming that Chrome doesn't download the file at all. I should have thought to ask... especially considering that Chrome is my personal browser of choice on all of my computers. :p

              rtcary;11019445 wrote:

              the code above is something I found on the Internet and hoped that it would cause a 404 page to appear

              That depends what you mean by "a 404 page." If the file doesn't exist, the user should receive a 404 status code in the HTTP response. Since you don't appear to send any data along with that status (e.g. an HTML document that explains the error), you should either see a blank page or perhaps some internal error page your browser decides to display when it detects it received an error response.

              rtcary;11019445 wrote:

              it does not.

              What does it do, then? Also, have you confirmed that you're at least getting the 404 status code in the response?

                bradgrafelman;11019421 wrote:

                I would also recommend adding the quotes that dalecosp omitted from his example above to ensure the file name isn't misunderstood (in case it later has a space in it).

                Good catch. I quoted that from working code that creates the file and enforces a specific filename, so the variable's clean there; in the event your file's coming from somewhere else ... caveat emptor and all that 😉

                  Write a Reply...