【问题标题】:Corrupt file when exporting PDF to a directory using ITextSharp使用 ITextSharp 将 PDF 导出到目录时文件损坏
【发布时间】:2020-09-02 13:30:18
【问题描述】:

我正在尝试使用 ITextSharp 生成 PDF,但是当我尝试打开它时,它指出它已损坏:

在我打开它之前,一切似乎都运行良好。

代码:

using (MemoryStream ms = new MemoryStream())
{
    Document document = new Document(PageSize.LETTER, 30, 30, 5, 5);
    PdfWriter writer = PdfWriter.GetInstance(document, ms);
    document.Open();

     // Style Code 

    #endregion

    document.Close();
    writer.Close();

    var result = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new ByteArrayContent(ms.GetBuffer())
    };

    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    result.Content.Headers.ContentDisposition.FileName = filename;
    string filePath = @"C:\Users\mmaslova\Desktop\TEMP\" + filename;
    FileStream stream = new FileStream(filePath, FileMode.Create);

    return result;
}

【问题讨论】:

    标签: c# asp.net itext


    【解决方案1】:

    这里有一个错误:

        Content = new ByteArrayContent(ms.GetBuffer())
    

    MemoryStream.GetBuffer() 返回可能比实际内容大得多的整个缓冲区。因此,您的Content 通常会包含一个带有大量垃圾字节尾部的 PDF。由于 PDF 处理器应该从其末尾读取 PDF(可以找到对对象交叉引用的引用),它会尝试在垃圾字节的末尾找到该引用。这失败了,因此文件已损坏。 (实际上,Adobe Reader 和其他处理器跟随它的领导在文件的最后 1024 字节中查找该引用。这增加了找到它的机会,但仍然有足够多的情况下找不到该引用。)

    你基本上有两个选择:

    • 要么改用MemoryStream.ToArray()。此方法仅返回实际内容,而不是未使用的尾随字节。缺点:它会创建这些字节的副本。根据您的 PDF 和资源的大小,这可能意味着麻烦。
    • 或者您仅将MemoryStream.GetBuffer() 与还接受表示该字节数组中实际内容长度的参数的方法一起使用,并将该参数设置为MemoryStream.Length

    例如在你的情况下ByteArrayContent 也有一个构造函数

    public ByteArrayContent (byte[] content, int offset, int count);
    

    (Microsoft docs on ByteArrayContent)

    所以你可以替换

        Content = new ByteArrayContent(ms.GetBuffer())
    

    通过

        Content = new ByteArrayContent(ms.GetBuffer(), 0, ms.Length)
    

    【讨论】:

      【解决方案2】:

      答案是我需要在 document.Open(); 之前移动 FileStream;

      答案:

      using (MemoryStream ms = new MemoryStream())
      {
           Document document = new Document(PageSize.LETTER, 30, 30, 5, 5);
           PdfWriter writer = PdfWriter.GetInstance(document, ms);
      
           string filePath = @"C:\Users\mmaslova\Desktop\TEMP\" + filename;
           PdfWriter.GetInstance(document, new FileStream(filePath, FileMode.Create));
           document.Open(); 
      
           #endregion
      
          document.Close();
          writer.Close();
      
          var result = new HttpResponseMessage(HttpStatusCode.OK)
          {
          
             Content = new ByteArrayContent(ms.GetBuffer())
        
          };
      
          result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
          result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
          result.Content.Headers.ContentDisposition.FileName = filename;
      
          return result;
      
      }
      

      【讨论】:

      • 在您的问题中,您没有提到您认为您没有写入任何内容的文件流的文件是为了包含 pdf,在您的问题中,您的意思似乎是 http 响应.您答案中的代码仍会将损坏的 pdf 发送给客户端。
      • @mkl 不是吗?我提到它正在发送损坏的 PDF。我不确定确切的原因。原来它正在发送 0 个字节。当我向上移动 FileStream 时,它起作用了....
      • 我有点困惑,你最终会提供文件吗?或者你服务HttpResponseMessage result?在后一种情况下,您所做的更改不应该有任何影响。在前一种情况下,HttpResponseMessage result 的填充是什么感觉?
      • 我正在使用 HttpResponseMessage,然后使用 IHttpActionResult 在另一个函数中调用它。
      • 所以你不要使用那个文件系统文件。因此,您的更改不应该有任何区别。实际上,您应该能够删除有关文件的所有内容而不会产生影响。
      猜你喜欢
      • 2011-01-12
      • 1970-01-01
      • 2016-01-25
      • 1970-01-01
      • 1970-01-01
      • 2016-10-02
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      相关资源
      最近更新 更多