Browser 如何在HTTP中对内容处置头的filename参数进行编码?
想要强制下载资源而不是直接在Web浏览器中呈现资源的Web应用程序在表单的HTTP响应中发出Browser 如何在HTTP中对内容处置头的filename参数进行编码?,browser,http-headers,specifications,Browser,Http Headers,Specifications,想要强制下载资源而不是直接在Web浏览器中呈现资源的Web应用程序在表单的HTTP响应中发出内容处置标题: 内容配置:附件;filename=文件名 filename参数可用于建议浏览器将资源下载到的文件的名称。但是,(内容处置)在(文件名参数)中指出,文件名只能使用US-ASCII字符: 当前[RFC 2045]语法限制 参数值(因此 内容处置(文件名)到 US-ASCII。我们承认伟大的 允许任意行为的可取性 文件名中的字符集,但它是 超出本文件的范围 确定必要的机制 然而,有经验证据表明,
内容处置
标题:
内容配置:附件;filename=文件名
filename
参数可用于建议浏览器将资源下载到的文件的名称。但是,(内容处置)在(文件名参数)中指出,文件名只能使用US-ASCII字符:
当前[RFC 2045]语法限制
参数值(因此
内容处置(文件名)到
US-ASCII。我们承认伟大的
允许任意行为的可取性
文件名中的字符集,但它是
超出本文件的范围
确定必要的机制
然而,有经验证据表明,当今最流行的Web浏览器似乎允许使用非美国ASCII字符,但(由于缺乏标准)在文件名的编码方案和字符集规范上存在分歧。问题是,如果文件名“naïvefile”(不带引号,其中第三个字母是U+00EF)需要编码到内容处理头中,流行浏览器采用的各种方案和编码是什么
就本问题而言,流行浏览器包括:
- 火狐
- Internet Explorer
- 狩猎
- 谷歌浏览器
- 歌剧院
表示此类标题应根据上述RFC草案中包含的内容进行编码。以下文件链接了作者在其回答中提到的内容,进一步解决了该问题,并在此处明确指出:
- 在
中没有可互操作的编码非ASCII名称的方法内容处置
- 在
中使用UTF-8的方法非常奇怪:内容配置
(是的,这是一个星号,中间只有一个空引号,没有引号)文件名*=UTF-8“foo%c3%a4
- 这个标题有点不太标准(,但不需要客户端支持)
/real_script.php/fake_filename.doc
如果您的服务器支持URL重写(例如Apache中的mod_rewrite
),那么您可以完全隐藏脚本部分
URL中的字符应为UTF-8,URL逐字节编码:
/mot%C3%B6rhead # motörhead
在asp.net mvc2中,我使用如下内容:
return File(
tempFile
, "application/octet-stream"
, HttpUtility.UrlPathEncode(fileName)
);
我想如果你不使用mvc(2),你可以使用
HttpUtility.UrlPathEncode(fileName)
我知道这是一个老帖子,但它仍然非常相关。我发现现代浏览器支持rfc5987,它允许utf-8编码、百分比编码(url编码)。然后Naïve file.txt变为:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari(5)不支持这一点。相反,您应该使用Safari标准,将文件名直接写入utf-8编码头中:
Content-Disposition: attachment; filename=Naïve file.txt
IE8和更早版本也不支持,您需要使用utf-8编码的IE标准,百分比编码:
Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt
在ASP.Net中,我使用以下代码:
字符串内容配置;
if(Request.Browser.Browser==“IE”&&(Request.Browser.Version==“7.0”| | Request.Browser.Version==“8.0”))
contentDisposition=“附件;文件名=“+Uri.EscapeDataString(文件名);
else if(Request.Browser.Browser==“Safari”)
contentDisposition=“附件;文件名=”+文件名;
其他的
contentDisposition=“附件;文件名*=UTF-8”“”+Uri.EscapeDataString(文件名);
AddHeader(“内容处置”,contentDisposition);
我使用IE7、IE8、IE9、Chrome 13、Opera 11、FF5和Safari 5测试了上述内容
更新2013年11月:
下面是我目前使用的代码。我仍然需要支持IE8,所以我无法摆脱第一部分。事实证明,Android上的浏览器使用内置的Android下载管理器,无法以标准方式可靠地解析文件名
字符串内容配置;
if(Request.Browser.Browser==“IE”&&(Request.Browser.Version==“7.0”| | Request.Browser.Version==“8.0”))
contentDisposition=“附件;文件名=“+Uri.EscapeDataString(文件名);
else if(Request.UserAgent!=null&&Request.UserAgent.ToLowerInvariant().Contains(“android”)//android内置下载管理器(android上的所有浏览器)
contentDisposition=“附件;文件名=\”“+MakeAndroidSafeFileName(文件名)+\”;
其他的
contentDisposition=“附件;文件名=\”“+filename+”\“文件名*=UTF-8”+Uri.EscapeDataString(文件名);
AddHeader(“内容处置”,contentDisposition);
以上内容现已在IE7-11、Chrome 32、Opera 12、FF25、Safari 6中测试,使用此文件名下载:你好abcABCæåØäýýýñ½§#¤%&()=`@£$€{[]}+´¨^~'-_,;.文本
在IE7上,它适用于某些字符,但不是所有字符。但如今谁在乎IE7呢
这是我用来为Android生成安全文件名的函数。请注意,我不知道Android上支持哪些字符,但我已经测试过这些字符是否确实有效:
private static readonly Dictionary AndroidAllowedChars=“abcdefghijklmnopqrstuvwxyzabdfghijklmnopqrstuvxyz.-+,@$€!½§~'=()[]{0123456789.”ToDictionary(c=>c);
私有字符串MakeAndroidSafeFileName(字符串文件名)
Content-Disposition: attachment;
filename="EURO rates";
filename*=utf-8''%e2%82%ac%20rates
$il1_filename = utf8_decode($filename);
$to_underscore = "\"\\#*;:|<>/?";
$safe_filename = strtr($il1_filename, $to_underscore, str_repeat("_", strlen($to_underscore)));
header("Content-Disposition: attachment; filename=\"$safe_filename\""
.( $safe_filename === $filename ? "" : "; filename*=UTF-8''".rawurlencode($filename) ));
public static class HttpRequestMessageExtensions
{
public static HttpResponseMessage CreateFileResponse(this HttpRequestMessage request, byte[] data, string filename, string mediaType)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new MemoryStream(data);
stream.Position = 0;
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType =
new MediaTypeHeaderValue(mediaType);
// URL-Encode filename
// Fixes behavior in IE, that filenames with non US-ASCII characters
// stay correct (not "_utf-8_.......=_=").
var encodedFilename = HttpUtility.UrlEncode(filename, Encoding.UTF8);
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment") { FileName = encodedFilename };
return response;
}
}
Content-Disposition: attachment; filename="My Report.doc"
header('Content-Disposition: attachment;'
. 'filename="' . addslashes(utf8_decode($filename)) . '";'
. 'filename*=utf-8\'\'' . rawurlencode($filename));
$filenameFallback = preg_replace('#^.*\.#', md5($filename) . '.', $filename);
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename, $filenameFallback);
$response->headers->set('Content-Disposition', $disposition);