12

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

var request = new GetPreSignedUrlRequest()
    .WithBucketName(S3BucketName)
    .WithExpires(requestExpirationTime)
    .WithKey(file.S3Key)
    .WithResponseHeaderOverrides(
        new ResponseHeaderOverrides()
            .WithContentDisposition("attachment; filename=\"Unicode FileName ᗩ Test.txt\""));

这会生成以下链接:

/s3path?AWSAccessKeyId=xxxx&Expires=1377199946&response-content-disposition=attachment%3B%20filename%3D"Unicode%20FileName%20ᗩ%20Test.txt"&Signature=xxxxx

这给出了这个错误:

<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>

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

4

2 回答 2

6

我遇到了这个问题,我通过正确编码 unicode 字符串来解决它。

我在python boto土地:

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

"Unicode%20%E1%97%A9%20filename.txt"

然后,将此编码字符串用作 response-content-disposition 标头的值。

在 Java 中,我相信您可以通过以下方式获得相同的结果:

URLEncoder.encode(original_string, "UTF-8")

希望这可以在某些时候对其他人有所帮助!

于 2014-02-21T12:08:21.670 回答
4

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

我们最终让它在所有浏览器中工作的方式是将所有非 ISO-8859-1 字符替换为“-”。这是代码:

private static readonly Encoding ContentDispositionHeaderEncoding = Encoding.GetEncoding("ISO-8859-1");

public static string GetWebSafeFileName(string fileName)
{
    // We need to convert the file name to ISO-8859-1 due to browser compatibility problems with the Content-Disposition Header (see: https://stackoverflow.com/a/216777/1038611)
    var webSafeFileName = Encoding.Convert(Encoding.Unicode, ContentDispositionHeaderEncoding, Encoding.Unicode.GetBytes(fileName));

    // Furthermore, any characters not supported by ISO-8859-1 will be replaced by « ? », which is not an acceptable file name character. So we replace these as well.
    return ContentDispositionHeaderEncoding.GetString(webSafeFileName).Replace('?', '-');
}

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

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

var type = typeof(System.Web.Util.HttpEncoder);
var methodInfo = type.GetMethod("UrlEncodeNonAscii", BindingFlags.NonPublic | BindingFlags.Instance, null, new [] { typeof(string), typeof(Encoding) }, null);
object[] parameters = {fileName, Encoding.UTF8};

var encoder = new System.Web.Util.HttpEncoder();

var encodedFileName = (string) methodInfo.Invoke(encoder, parameters);
于 2014-02-21T17:03:14.943 回答