We're using this code to generate requests and set the filename for the download:
var request = new GetPreSignedUrlRequest()
.WithBucketName(S3BucketName)
.WithExpires(requestExpirationTime)
.WithKey(file.S3Key)
.WithResponseHeaderOverrides(
new ResponseHeaderOverrides()
.WithContentDisposition("attachment; filename=\"Unicode FileName ᗩ Test.txt\""));
This generates the following link:
/s3path?AWSAccessKeyId=xxxx&Expires=1377199946&response-content-disposition=attachment%3B%20filename%3D"Unicode%20FileName%20ᗩ%20Test.txt"&Signature=xxxxx
Which gives this error:
<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>
How can we use non-ISO-8859-1 characters, such as unicode, in the response-content-disposition header?
I had this issue and I solved it by encoding the unicode string correctly.
I was in python boto land:
>>> import urllib
>>> encoded = urllib.quote('Unicode FileName ᗩ Test.txt')
>>> print encoded
"Unicode%20%E1%97%A9%20filename.txt"
Then, use this encoded string as the value for the response-content-disposition header.
In Java I believe you can achieve the same result with:
URLEncoder.encode(original_string, "UTF-8")
Hope this helps someone else at some point!
As mentioned by this StackOverflow answer, There is no interoperable way to encode non-ASCII names in Content-Disposition. Browser compatibility is a mess.
The way we ended up doing it so that it works in all browsers is to replace all non-ISO-8859-1 characters by '-'. Here's the code:
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('?', '-');
}
Following Alex Couper's answer, I found a way in .net to encode only non-ascii characters by calling an internal method in HttpEncoder
Calling internal functions is not recommended as they may change in future versions of the framework! Furthermore this will not work in all browsers as mentioned above. I'm leaving this here in case someone absolutely needs to do this.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With