移动设备中使用HTTP头部"Content-Type: application/force-download"的效用是什么?

51
我目前正在开发一个PHP脚本,可以通过访问链接(例如http://www.my-web-site.com/download.php?id=7ejs8ap)从您的移动设备下载媒体内容(视频、音频、图片等)。在最新的移动设备(三星Galaxy S、iPhone 4S等)上测试时,我的脚本运行得非常好,但是在我的老款三星C3050手机上出现了错误。我想下载的媒体只是一个通常可以轻松下载的音频mp3文件。

错误显示为“未知内容类型”。 因此,由于我的唯一HTTP头Content-Type是“application/force-download”,我尝试注释它然后再试一次。 然后,它就可以工作了。 但现在,我正在询问这个Content-Type是什么意思,它是否对其他手机必需。 我在iPhone 4上测试过没有Content-Type也可以工作,但是我不确定所有移动设备是否兼容。

有人能解释一下Content-Type如何工作,为什么这不是标准MIME或任何其他能帮助我确保对于任何下载,无论文件、浏览器或我正在下载的设备来说都是可选的Content-Type吗?

谢谢大家。

这是我发送的 PHP headers:

<?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);
?>

编辑:我刚刚尝试了一下索尼Xperia,下载没有成功:我只看到了我想要下载的文件的“html编码”字节。如果application/octet-stream或application/force-download不起作用,我怎么知道我必须使用哪种content-type?

3个回答

137

Content-Type: application/force-download 表示“我,Web 服务器,将欺骗你(浏览器)关于这个文件的类型,以便你不会将其视为PDF / Word文档/ MP3 / 等等并提示用户将神秘的文件保存到磁盘上”。这是一个肮脏的黑客技巧,当客户端不进行“保存到磁盘”操作时,它会严重破坏。

使用正确的媒体类型(例如mp3的音频/mpeg)。

如果您希望客户端下载而非按照默认行为执行操作,请使用Content-Disposition: attachment; etc etc头。


谢谢您的解释。我将尝试使用application/octet-stream,如果不起作用,我将使用一个函数从文件名中检测mime类型。我希望这对于像*.m4r或*.dm这样的一些“特殊”文件能够起作用,例如特殊的iPhone铃声... 如果不行,我将不得不自己编写繁琐的switch/case :'( - niconoe
1
@nioconoe 找出文件的 MIME 类型最简单的方法是使用 fileinfo 库。在 PHP 中,它是 http://www.php.net/manual/zh/function.finfo-file.php。您也可以从命令行运行 file --mime <filename> - Mark E. Haase
如果内容本身是一个HTML页面呢?(例如,一个HTML报告)? - D34dman
@Quentin 谢谢你澄清 :) 我正在生成一个HTML报告(而且屏幕上已经显示了一个更好的报告)。所以在这个页面上有一个下载链接,我问自己,用户是否真的需要在保存到磁盘之前确认它!这不是一个必要的步骤吗?看起来这是一件不好的事情。我不想让我的应用程序被贴上骗子的标签 :). 应该小心简化工作流程和其他东西。 - D34dman
@Quentin 我在这里感到有点自豪,授予您100个赞和一个金徽章,好答案! - Eugene

18

要下载文件,请使用以下代码...将文件名与位置存储在$file变量中。它支持所有mime类型。

$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);

了解Mime类型,请查看此链接:http://php.net/manual/en/function.mime-content-type.php


尽管此函数已被弃用,但我可以阅读一些关于 MIME 类型的解释,所以谢谢。 但是,它并没有解释为什么应用程序/force-download 不是所有浏览器都认可的内容类型... - niconoe
13
HTTP中不存在Content-Description和Content-Transfer-Encoding。有关缓存的所有头文件可能都是无用的。最后,对于许多$file的值,Content-Disposition标头将无效。请参见RFC6266。 - Julian Reschke
Suresh,mime_content_type函数现在被认为是过时的。 - catfood
1
问题:为什么要使用flush()和ob_clean()? - Jabran Saeed
1
如在其他地方所述:请优先使用真正的Content-Type而不是“Content-Type: application/octet-stream”。 - Pierre-Olivier Vares
我在使用.Net进行下载时遇到了问题,按照这个顺序使用这些标头帮助我解决了其他示例失败的问题。谢谢! - user1532208

4

application/force-download并非标准MIME类型,而是一种由某些浏览器支持、近期添加的技巧。

你的问题并不合适。这就像问为什么Internet Explorer 4不支持最新的CSS 3功能一样。


我知道这不是标准的 MIME 类型,但我不知道最近增加了它。我明白你告诉我我的问题毫无意义,但是为什么,当我在没有这个“Content-Type hack” 的情况下尝试我的 Sony Xperia 时,它就不能再工作了呢? 看起来这将用于我们的浏览器,因为它们不喜欢使用标准... - niconoe
4
根据定义,当你使用非标准内容类型时,实现是未定义的。浏览器所做的任何事情在技术上都是“正确”的。你可以将内容类型设置为“application/sadjkfhlaksdjdkfjgh”,并实现完全相同的效果。 - Jon Grant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接