如何在S3的response-content-disposition头中使用unicode字符?

ECC*_*Dan 9 c# amazon-s3 amazon-web-services

我们使用此代码生成请求并设置下载文件名:

var request = new GetPreSignedUrlRequest()
    .WithBucketName(S3BucketName)
    .WithExpires(requestExpirationTime)
    .WithKey(file.S3Key)
    .WithResponseHeaderOverrides(
        new ResponseHeaderOverrides()
            .WithContentDisposition("attachment; filename=\"Unicode FileName ? Test.txt\""));
Run Code Online (Sandbox Code Playgroud)

这会生成以下链接:

/s3path?AWSAccessKeyId=xxxx&Expires=1377199946&response-content-disposition=attachment%3B%20filename%3D"Unicode%20FileName%20?%20Test.txt"&Signature=xxxxx
Run Code Online (Sandbox Code Playgroud)

这给出了这个错误:

<Error>
    <Code>InvalidArgument</Code>
    <Message>
        Header value cannot be represented using ISO-8859-1.
    </Message>
    <ArgumentValue>attachment; filename="Unicode ? filename.txt"</ArgumentValue>
    <ArgumentName>response-content-disposition</ArgumentName>
    <RequestId>368BD60502854514</RequestId>
    <HostId>
        BiUUYp4d9iXfK68jKVxWZEp25m5je166M0ZY1VmoPk9pN9A69HLHcff6WIVLWk1B
    </HostId>
</Error>
Run Code Online (Sandbox Code Playgroud)

我们如何在response-content-disposition头中使用非ISO-8859-1字符,例如unicode?

Ale*_*per 6

我有这个问题,我通过正确编码unicode字符串解决了它.

我在python boto土地:

>>> import urllib
>>> encoded = urllib.quote('Unicode FileName ? Test.txt')
>>> print encoded

"Unicode%20%E1%97%A9%20filename.txt"
Run Code Online (Sandbox Code Playgroud)

然后,使用此编码的字符串作为response-content-disposition标头的值.

在Java中我相信你可以用以下方法获得相同的结果:

URLEncoder.encode(original_string, "UTF-8")
Run Code Online (Sandbox Code Playgroud)

希望这在某些方面帮助别人!


ECC*_*Dan 6

正如StackOverflow 答案中提到的,在 Content-Disposition 中没有可互操作的方法来编码非 ASCII 名称。浏览器兼容性一团糟。

\n\n

我们最终的方法是用 \'-\' 替换所有非 ISO-8859-1 字符,以便它在所有浏览器中都能工作。这是代码:

\n\n
private static readonly Encoding ContentDispositionHeaderEncoding = Encoding.GetEncoding("ISO-8859-1");\n\npublic static string GetWebSafeFileName(string fileName)\n{\n    // We need to convert the file name to ISO-8859-1 due to browser compatibility problems with the Content-Disposition Header (see: /sf/answers/15174421/)\n    var webSafeFileName = Encoding.Convert(Encoding.Unicode, ContentDispositionHeaderEncoding, Encoding.Unicode.GetBytes(fileName));\n\n    // Furthermore, any characters not supported by ISO-8859-1 will be replaced by \xc2\xab ? \xc2\xbb, which is not an acceptable file name character. So we replace these as well.\n    return ContentDispositionHeaderEncoding.GetString(webSafeFileName).Replace(\'?\', \'-\');\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

根据Alex Couper的回答,我在.net中找到了一种通过调用HttpEncoder中的内部方法来仅对非ascii字符进行编码的方法

\n\n

不建议调用内部函数,因为它们可能在框架的未来版本中发生变化!此外,如上所述,这不适用于所有浏览器。我将其留在这里,以防有人绝对需要这样做。

\n\n
var type = typeof(System.Web.Util.HttpEncoder);\nvar methodInfo = type.GetMethod("UrlEncodeNonAscii", BindingFlags.NonPublic | BindingFlags.Instance, null, new [] { typeof(string), typeof(Encoding) }, null);\nobject[] parameters = {fileName, Encoding.UTF8};\n\nvar encoder = new System.Web.Util.HttpEncoder();\n\nvar encodedFileName = (string) methodInfo.Invoke(encoder, parameters);\n
Run Code Online (Sandbox Code Playgroud)\n