【问题标题】:Custom filename not shown when viewing inline file in ASP.NET Core 2.2 MVC在 ASP.NET Core 2.2 MVC 中查看内联文件时未显示自定义文件名
【发布时间】:2018-12-11 11:17:23
【问题描述】:

我想从第三方系统传送附件。它们在文件系统中存储为.attach 文件,原始文件存在于他的数据库中。跟随this approach,我的动作是这样的:

    public async Task<IActionResult> GetAttachment(int id) {
        var attachment = await myAttachmentManager.GetAttachmentAsync(id);
        // attachmentsPath = T:\attachments, FilePath = 1234.attach
        string fullPath = Path.Combine(attachmentsPath, attachment.FilePath); 
        var content = await File.ReadAllBytesAsync(fullPath);

        var fileContentProvider = new FileExtensionContentTypeProvider();
        string mimeType;
        if (!fileContentProvider.TryGetContentType(attachment.FileName, out mimeType)) // FileName = my-file.pdf
            mimeType = "application/octet-stream";
        var file = new FileContentResult(content, mimeType);

        // This should display "my-file.pdf" as title
        var contentHeader = new ContentDispositionHeaderValue("inline") {
            FileName = attachment.FileName
        }.ToString();
        Response.Headers["Content-Disposition"] = contentHeader;

        return file;
    }

这可行,pdf 文件嵌入在浏览器中,并且下载了 zip 等二进制文件。但是在查看 pdf 时,浏览器会在这些示例中显示 1234.attach 作为标题。我想显示真实的文件名(这里是my-pdf.pdf)并找到了Content-Disposition这个标题。

尽管如此,Firefox 和 Chrome 仍然显示 id 而不是 my-pdf.pdf。检查页面时,它会显示这些标题标签:

<title>1234</title>

我做错了什么?

避免将文件名设置为id

找到this question,似乎id get 参数被用作文件名。在我的情况下,它是一个真实的数字 id (1234),我需要保留它,因为文件已由使用这些 id 的数据库验证。

【问题讨论】:

    标签: c# http asp.net-core download asp.net-core-2.2


    【解决方案1】:

    Chrome pdf Viewer 似乎会读取 pdf 文件,并使用 pdf 文档的 Title 作为您页面的标题

    再现

    为了测试,我们先下载the MQTT protocol standardTitle 属性位于第 7184 行

    <</Title(MQTT Version 3.1.1) /Author(OASIS Message Queuing Telemetry Transport \(MQTT\) TC) /Creator .... >>
    

    该行表示此 pdf 文档的标题为:MQTT Version 3.1.1

    现在让我们用 Chrome 测试这个 pdf 文件。向/home/getattachment/123.pdf发送一个HTTP请求:

    GET /home/getattachment/123.pdf HTTP/1.1
    Host: localhost:5001
    Connection: keep-alive
    Pragma: no-cache
    Cache-Control: no-cache
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding: gzip, deflate, br
    Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
    

    并且来自服务器的HTTP响应是:

    HTTP/1.1 200 OK
    Content-Type: application/pdf
    Server: Kestrel
    Transfer-Encoding: chunked
    Content-Disposition: inline; filename=wont_work_mqtt-v3.1.1-os.pdf; filename*=UTF-8''wont_work_mqtt-v3.1.1-os.pdf
    

    注意url的最后一段是123.pdf我们在Content-Disposition中指定文件名为wont_work_mqtt-v3.1.1-os.pdf

    下面的截图显示Tab的标题pdf视图的标题都是pdf文档的原始Title

    漫游

    如果我将 pdf 文档的 Title 属性更改为 (itminus_MQTT Version 3.1.1),如下所示:

    <<
    /Title (itminus_MQTT Version 3.1.1)
    /CreationDate (D:20141105132636-05'00')
    /ModDate (D:20141105132636-05'00')
    /Author (OASIS Message Queuing Telemetry Transport \(MQTT\) TC)
    /Producer (Select.Pdf for .NET v2018.4.0)
    /Creator (Microsoft� Word 2010)
    >>
    

    响应将是:

    所以一个解决方法是修改 pdf 文档的 Title 属性。你可以选择你最喜欢的库来做你喜欢的。这里我使用SelectPdf 进行测试:

    var cdhv= new ContentDispositionHeaderValue("inline");
    cdhv.SetHttpFileName( attachmentFileName);
    Response.Headers["Content-Disposition"] = cdhv.ToString();
    if(mimeType == "application/pdf"){
        SelectPdf.PdfDocument doc = null;
        try{
            doc = new SelectPdf.PdfDocument(fullPath);
            var docinfo = doc.DocumentInformation;
            docinfo.Title = attachmentFileName;
            doc.Save(Response.Body);
        }finally{
            doc?.Close();
        }
    }else{
        Response.Body.Write(content);
    }
    return ;
    

    它对我有用。

    【讨论】:

      【解决方案2】:

      您应该设置 FileContentResult 的 FileDownloadName 属性

      byte[] content = your_byte[];
      
      FileContentResult result = new FileContentResult(content, "application/octet-stream") 
                       {
                           FileDownloadName = String.Format("{0}.csv", fileName)
                       };
      
      return result;
      

      var file = new FileContentResult(content, mimeType);
      file.FileDownloadName = String.Format("{0}.csv", fileName);
      

      【讨论】:

      • 已经尝试过:当设置FileDownloadName 时,不能嵌入PDF 视图。相反,他们被下载了。确实具有正确的文件名,但我想尽可能嵌入 pdf 或图像等文件以提高可用性。没有FileDownloadName,嵌入至少可以工作,尽管它显示了一个非语音文件名。
      • 看看这个answer,它可能会有所帮助
      • 我没有使用HttpResponseMessage,但我尝试了PhysicalFileResult。由于该类将我的代码缩短了一点,它很有用,但它的行为是相同的:由于设置了FileDownloadName 属性,因此下载的 pdf 文件的名称是正确的。如果没有该属性,文件将被嵌入,但 1234 id 作为浏览器中的选项卡标题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      • 2020-11-10
      • 2023-04-08
      • 1970-01-01
      • 2016-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多