在某些情况下,您的标题很可能有问题。
生成正确的Content-Disposition
标头比这要复杂一些。最好从框架中已有的实现开始,只有在真正需要时才使用RFC 2231 ,如下所示:
public class ContentDispositionUtil
{
public static string GetContentDisposition(string fileName)
{
try
{
return (new ContentDisposition() { FileName = fileName }).ToString();
}
catch (FormatException)
{
return GetRfc2231ContentDisposition(fileName);
}
}
}
的实现GetRfc2231ContentDisposition
是棘手的部分。通常,您需要检查文件名中的每个字符是否对标头有效,如果没有正确编码。可以通过以下方法进行检查:
private static bool IsValidRfc2231ContentDispositionCharacter(byte character)
{
if ((byte)'0' <= character && character <= (byte)'9')
return true;
if ((byte)'a' <= character && character <= (byte)'z')
return true;
if ((byte)'A' <= character && character <= (byte)'Z')
return true;
switch (character)
{
case (byte)'-':
case (byte)'.':
case (byte)'_':
case (byte)'~':
case (byte)':':
case (byte)'!':
case (byte)'$':
case (byte)'&':
case (byte)'+':
return true;
}
return false;
}
简单的实现,但它显示了哪些字符是允许的。现在你可以像这样进行编码:
private const string _hexDigits = "0123456789ABCDEF";
private static string EncodeInvalidRfc2231ContentDispositionCharacter(int character)
{
return "%" + _hexDigits[character >> 4] + _hexDigits[character % 16];
}
现在我们准备好生成标头:
private static string GetRfc2231ContentDisposition(string filename)
{
StringBuilder contentDispositionBuilder = new StringBuilder("attachment; filename*=UTF-8''");
byte[] filenameBytes = Encoding.UTF8.GetBytes(filename);
foreach (byte character in filenameBytes)
{
if (IsValidRfc2231ContentDispositionCharacter(character))
contentDispositionBuilder.Append((char)character);
else
{
contentDispositionBuilder.Append(EncodeInvalidRfc2231ContentDispositionCharacter((int)character));
}
}
return contentDispositionBuilder.ToString();
}
现在你应该总是得到正确的标题。
PS 当然,只有在真正需要时才执行所有这些操作,并FileResult
尽可能使用内置的操作结果;)