【问题标题】:Angular/Web API 2 returns invalid or corrupt file with StreamContent or ByteArrayContentAngular/Web API 2 使用 StreamContent 或 ByteArrayContent 返回无效或损坏的文件
【发布时间】:2016-06-14 21:44:00
【问题描述】:

我正在尝试在 ASP.NET Web API 控制器中返回一个文件。此文件是保存在 MemoryStream 中的动态生成的 PDF。

客户端(浏览器)成功接收到文件,但是打开文件后发现所有页面都是空白的。

问题是,如果我把相同的 MemoryStream 写入一个文件,这个磁盘文件会正确显示,所以我认为问题与通过 Web 传输文件有关。

我的控制器如下所示:

[HttpGet][Route("export/pdf")]
public HttpResponseMessage ExportAsPdf()
{
    MemoryStream memStream = new MemoryStream();
    PdfExporter.Instance.Generate(memStream);

    memStream.Position = 0;
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new ByteArrayContent(memStream.ToArray()); //OR: new StreamContent(memStream);
    return result;
}

只是试一试,如果我将流写入磁盘,它会正确显示:

[HttpGet][Route("export/pdf")]
public HttpResponseMessage ExportAsPdf()
{
    MemoryStream memStream = new MemoryStream();
    PdfExporter.Instance.Generate(memStream);

    memStream.Position = 0;
    using (var fs = new FileStream("C:\\Temp\\test.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite))
    {
        memStream.CopyTo(fs);
    }

    return null;
}

区别在于:

  • 保存在磁盘上的 PDF:34KB
  • 通过网络传输的 PDF:60KB (!)

如果我比较两个文件的内容,主要区别是:

File Differences

左边是通过网络传输的PDF;在右侧,PDF 保存到磁盘。

我的代码有问题吗? 也许与编码有关?

谢谢!

【问题讨论】:

    标签: c# angularjs asp.net-web-api asp.net-web-api2 memorystream


    【解决方案1】:

    嗯,原来是客户端(浏览器)问题,而不是服务器问题。我在前端使用 AngularJS,所以当收到响应时,Angular 会自动将其转换为 Javascript 字符串。在那次转换中,文件的二进制内容被某种方式改变了……

    基本上是通过告诉 Angular 不要将响应转换为字符串来解决的:

    $http.get(url, { responseType: 'arraybuffer' })
    .then(function(response) {
        var dataBlob = new Blob([response.data], { type: 'application/pdf'});
        FileSaver.saveAs(dataBlob, 'myFile.pdf');
    });
    

    然后在Angular File Saver 服务的帮助下将响应保存为文件。

    【讨论】:

      【解决方案2】:

      我猜你应该像这样设置ContentDisposition 和ContentType:

      [HttpGet][Route("export/pdf")]
      public HttpResponseMessage ExportAsPdf()
      {
          MemoryStream memStream = new MemoryStream();
          PdfExporter.Instance.Generate(memStream);
      
          var result = new HttpResponseMessage(HttpStatusCode.OK)
          {
              Content = new ByteArrayContent(memStream.ToArray())
          };
          //this line
          result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
          {
              FileName = "YourName.pdf"
          };
          //and this line
          result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
          return result;
      }
      

      【讨论】:

      • 对不起,但没有运气:(同样的结果。需要指出的是:memStream.GetBuffer() 返回一个 ~64K 字节数组,而 memStream.ToArray() 返回一个 ~34K 字节数组...
      • 不要使用 GetBuffer(),因为它返回一个固定大小的数组...使用 ToArray()。
      • 不敢相信从 GetBuffer() 更改为 ToArray() 为我解决了这个问题。谢谢你。我花了几个小时。
      【解决方案3】:

      试试这个

      [HttpGet][Route("export/pdf")]
      public HttpResponseMessage ExportAsPdf()
      {
          MemoryStream memStream = new MemoryStream();
          PdfExporter.Instance.Generate(memStream);
      
          //get buffer
          var buffer = memStream.GetBuffer();
          //content length for header
          var contentLength = buffer.Length;
      
          var statuscode = HttpStatusCode.OK;
          var response = Request.CreateResponse(statuscode);
          response.Content = new StreamContent(new MemoryStream(buffer));
          response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
          response.Content.Headers.ContentLength = contentLength;
          ContentDispositionHeaderValue contentDisposition = null;
          if (ContentDispositionHeaderValue.TryParse("inline; filename=my_filename.pdf", out contentDisposition)) {
              response.Content.Headers.ContentDisposition = contentDisposition;
          }
      
          return response;
      }
      

      【讨论】:

      • 不幸的是,同样的结果......就像没有任何改变一样。
      猜你喜欢
      • 2023-03-25
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 2020-03-21
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多