使用ASP.NET Core MVC中的UTF-8(泰语)文件名下载文件



我创建了一个用于下载文件的函数,除了文件名之外,它可以正常工作。当我下载带有泰语名称的文件时,其名称变成了HTML实体。

例如:

  • 原始文件名:ไฟล์_1_ข้อมูลลูกค้า__Customer_Information_.xml
  • 保存文件名:"ไฟล์_1_ข้อมูลลูกค้า__Customer_Information_.xml".

如何用原始名称保存文件?这是我的代码:

[HttpGet]
public async Task<IActionResult> DownloadOtherFile(string id, string filename)
{
    string trueFileName = HttpUtility.HtmlDecode(filename);
    var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", filename);
    HttpClient client = new HttpClient
    {
        BaseAddress = new Uri(option.ApiBaseUrl)
    };
    try
    {
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", HttpContext.Session.GetString("token"));
        HttpResponseMessage response = await client.GetAsync("/file/other/job/" + id + "/" + trueFileName);
        var content = await response.Content.ReadAsStreamAsync();
        return File(content, "APPLICATION/octet-stream", trueFileName);
    }
    catch (Exception)
    {
        //error
    }
    finally
    {
        client.Dispose();
    }
    return null;
}

长话短说,标题值仅接受ISO-8859-1字符,因此始终编码非ASCII字符。客户应该能够识别编码。如果不是,这是客户的问题。asp.net core die 遵循源代码显示的标准。

内容类型标头不接受文件名。该文件名在内容插入标题中指定。

用特定名称返回文件的正确方法是使用文件(流,字符串,字符串(方法或将文件名作为Content-Disposition标头的一部分传递。

您应该替换:

return File(content, "APPLICATION/octet-stream, trueFileName");

with:

return File(content, "application/octet-stream", trueFileName);

update

我不能再现任何问题。我创建了一个新的ASP.NET Core MVC应用程序,其Home/Index方法仅为:

public IActionResult Index()
{
    var trueFileName = "ไฟล์_1_ข้อมูลลูกค้า__Customer_Information_.xml";
    var bytes=Encoding.UTF8.GetBytes("Hello");
    return File(bytes, "APPLICATION/octet-stream", trueFileName);            
}

浏览该URL下载了一个名称为

的文件
ไฟล์_1_ข้อมูลลูกค้า__Customer_Information_.xml

我用铬,Firefox和Edge Chromium对此进行了测试。

该名称未编码HTML,它是按照应有的方式编码的。原始的HTTP响应是:

HTTP/1.1 200 OK
Date: Tue, 06 Aug 2019 15:13:54 GMT
Content-Type: APPLICATION/octet-stream
Server: Kestrel
Content-Length: 5
Content-Disposition: attachment; filename=_____1_______________Customer_Information_.xml; filename*=UTF-8''%E0%B9%84%E0%B8%9F%E0%B8%A5%E0%B9%8C_1_%E0%B8%82%E0%B9%89%E0%B8%AD%E0%B8%A1%E0%B8%B9%E0%B8%A5%E0%B8%A5%E0%B8%B9%E0%B8%81%E0%B8%84%E0%B9%89%E0%B8%B2__Customer_Information_.xml
Hello

更新2

该文件名作为URL参数从客户端传递,并且可能编码两次。这是HtmlDecode产生另一个HTML编码字符串的唯一方法。

此通话:

var fileName="&#xE44;&#xE1F;&#xE25;&#xE4C;_1_&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;__Customer_Information_.xml";
var actualName=HttpUtility.HtmlDecode(fileName);

返回:

ไฟล์_1_ข้อมูลลูกค้า__Customer_Information_.xml

我怀疑该字符串被编码两次。

解决此类问题的问题是快速的第一步是使用Fiddler之类的调试代理来捕获和检查HTTP请求和响应。这不需要在服务器或客户端上进行任何更改。

类似的工具是所有现代浏览器的开发人员工具中的Network选项卡。

另一个选项是更改Web应用程序的记录配置以记录请求和响应。这只能在测试或调查问题期间完成,因为它会产生文本的 lot 并减慢应用程序

最新更新