Utility of HTTP header "Content-Type: application/force-download" for mobile?
Asked Answered
M

3

51

I am currently working on a PHP script that allows you to download media contents (video, audio, pictures...) from your mobile device by accessing a link. (i.e. http://www.my-web-site.com/download.php?id=7ejs8ap) My script worked very vell when I was testing it with recent mobile (Samsung Galaxy S, iPhone 4S, some others...) but an error occured on my old mobile Samsung C3050. The media I wanted to download was just an audio mp3 file that I usually download easily.

The error appears to be "Unknown content type." So, as my only HTTP header Content-Type was "application/force-download", I try to comment this and try again. Then, it works. But now, I am currently asking what this Content-Type means and if it can be mandatory for others mobile. I tested without the Content-Type on the iPhone 4 and it works, but I'm not sure of this compatibility for all mobile.

Can someone explain me how that Content-Type works, why this isn't a standard MIME or everything else that can help me to be sure this is an optionnal Content-Type for every download, whatever the file, the browser or the device I am downloading on?

Thanks everyone.

Here is my PHP headers sent:

<?php
//Assume that $filename and $filePath are correclty set.
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="'.$filename.'"');
// header('Content-Type: application/force-download'); Non-standard MIME-Type, incompatible with Samsung C3050 for example. Let it commented
readfile($filePath);
?>

EDIT : I just tried with a Sony Xperia, and the download wasn't successful: I only see the "html-encoded" bytes of my file I want to download. How can I know what content-type I have to use if application/octet-stream or application/force-download doesn't work?

Marutani answered 16/5, 2012 at 9:34 Comment(0)
R
138

Content-Type: application/force-download means "I, the web server, am going to lie to you (the browser) about what this file is so that you will not treat it as a PDF/Word Document/MP3/whatever and prompt the user to save the mysterious file to disk instead". It is a dirty hack that breaks horribly when the client doesn't do "save to disk".

Use the correct mime type for whatever media you are using (e.g. audio/mpeg for mp3).

Use the Content-Disposition: attachment; etc etc header if you want to encourage the client to download it instead of following the default behaviour.

Ribbentrop answered 16/5, 2012 at 10:34 Comment(5)
Thank you for your explanations. I'll try later the application/octet-stream and if it doesn't work, I'm gonna use a function to detect the mime-type from a filename. I hope this will work for some "special" file I have like *.m4r or *.dm for special iPhone ringtones for example... If not, I will do my own unwanted switch/case :'(Marutani
@nioconoe The easiest way to figure out a mime type for a file is to the fileinfo library. In PHP, it is php.net/manual/en/function.finfo-file.php. You can also run file --mime <filename> from a command line.Cobelligerent
What if the content itself is an html page? ( example an html report ) ?Heerlen
@Ribbentrop thanks for clarifying :) i was generating an html report (and a much better report was already being displayed on the screen). So there is this download link on this page and i asked myself, does the user really have to confirm it before saving it to disk! isn't that an un-necessary step. So its a dirty thing to do it seems. And i don't want my application to be labelled a liar :). Should be careful about simplifying workflow and stuff.Heerlen
@Ribbentrop I feel sort of proud here, awarding you the 100 up-vote and a gold badge, good answer!Ajani
L
18

To download a file please use the following code ... Store the File name with location in $file variable. It supports all mime type

$file = "location of file to download"
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);

To know about Mime types please refer to this link: http://php.net/manual/en/function.mime-content-type.php

Lujan answered 16/5, 2012 at 9:42 Comment(6)
Although this function is deprecated, I can read some explanations on MIME-type, so thank you. But, it doesn't explain me why application/force-download is not a recognized content-type for all browsers...Marutani
Content-Description does not exist in HTTP. Content-Transfer-Encoding does not exist in HTTP. (See iana.org/assignments/message-headers/perm-headers.html). All of the cache related headers are probably useless. Finally, the Content-Disposition header will be invalid for many values of $file. See RFC 6266.Odum
Suresh, the mime_content_type function is now considered deprecated.Hadden
Question: why are you using flush() and ob_clean()Sanitary
As said elsewhere : prefer using the real Content-Type, not "Content-Type: application/octet-stream".Resile
I was having issues downloading in .Net and using these headers in this order helped me solve the problem where other examples failed. Thanks!Gibbosity
S
4

application/force-download is not a standard MIME type. It's a hack supported by some browsers, added fairly recently.

Your question doesn't really make any sense. It's like asking why Internet Explorer 4 doesn't support the latest CSS 3 functionality.

Salic answered 16/5, 2012 at 10:36 Comment(2)
I know that it's not a standard MIME type, but I didn't know it was added recently. I unsertand you telling me my question doesn't make any sense, but why, when I tried with my Sony Xperia without this "Content-Type hack", it doesn't work anymore? It seems this will be used for our browsers which dislike work with standard...Marutani
Because by definition when you use a non-standard content type, the implementation is undefined. Anything the browser does is technically "correct". You could just as easily set the content type to "application/sadjkfhlaksdjdkfjgh" and achieve the exact same effect.Salic

© 2022 - 2024 — McMap. All rights reserved.