我在Node.js中的标准http
模块上编写了一个Web服务器。它一直像我一样为我提供服务各种HTML,JavaScript,CSS和资产内容的工作 - 自然地构成了我的大部分网页。
当请求服务的URL映射到扩展名未知的文件(没有进行MIME嗅探)时,它只使用带有标题Content-Type: application/octet-stream
的分块传输编码来提供内容,该标题一直在工作奇妙的是 - 我偶尔会在服务器上托管各种文件,并且能够在不受用户代理干扰的情况下下载这些文件,因为我期望application/octet-stream
处理。
然而,今天,我尝试在iPhone 4S上的iOS 9.3.5上运行的Safari移动浏览器上下载,并且很明显拒绝从有效的URL下载,提醒我:
下载失败。 Safari无法下载此文件。
我试图添加Content-Disposition: attachment
和Content-Disposition: attachment; filename="foobar"
以获得良好的衡量标准,但它仍然拒绝。
这是一个名为random
的文件,它填充了1000个随机字节。我的主机标头是(Content-Disposition
是可选的,如上所述):
HTTP/1.1 200 OK
Host: example.com
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="foobar"
Date: Mon, 01 May 2017 13:48:37 GMT
Connection: keep-alive
Transfer-Encoding: chunked
为了记录,Android 6.x手机的行为也符合预期(除了我的Windows 10 x86_64主机上的Firefox 53),从URL下载顺利。
Safari在这里发生了什么?
答案 0 :(得分:4)
是的,您可以在iOS上使用Safari下载的唯一内容是图像。这是因为iOS没有向用户公开文件结构(下载文件到用户永远看不到的地方没有任何意义),它与反网络攻击无关。 Android上的浏览器可以下载任意文件,因为用户可以看到Android文件结构。
以前是关于Apple社区的讨论:https://discussions.apple.com/thread/3697948?start=0&tstart=0
您可以从Safari保存到iPhone的唯一内容是图片。没有别的,没有下载。
以后可能会下载iOS支持的视频文件,但对于application/octet-stream
MIME类型的任意文件不太可能。
答案 1 :(得分:0)
在花了很多时间试图找到解决方案之后,我想到了这个解决方案:
用pdf替换八位字节流。
<?php
$file = 'data/report/foobar.pdf';
header('Content-Description: File Transfer');
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="'.$file.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: '.filesize($file));
readfile($file);
?>