2012-06-05 55 views
1

我正在使用iTextSharp和VB.Net将图像印到PDF文档上。 (因为这不是我为C#标记的特定语言)。我有两个应用程序使用这个过程。PDF将文件流移动到文件流时,文件已损坏,无法修复

  • 第一次使用来自存储流的字节来在线显示PDF 文档。这件作品正在运作。

  • 第二个使用相同的功能,但将PDF保存到 文件。这件作品会生成无效的PDF。

我已经看到一些类似的问题,但它们都是最初创建一个文档并在代码中有一个文档对象。他们的记忆流从一开始就是腐败的。我的代码没有文档对象,我的原始内存流打开正常。

这里是我的错误的地方:(我必须把缓冲区从M转换成新的内存流,因为在fillPDF功能默认为关闭流压模除非标记,否则)

Dim m As MemoryStream = PDFHelper.fillPDF(filename, Nothing, markers, "") 
Dim m2 As New MemoryStream(m.GetBuffer, 0, m.GetBuffer.Length) 
Dim f As FileStream = New FileStream("C:\temp.pdf", FileMode.Create) 
m2.CopyTo(f, m.GetBuffer.Length) 
m2.Close() 
f.Close() 

这是我在网站上成功使用它的方法之一。这一个不使用图像,虽然一些其他类似的成功的地方在多个文档上使用图像,然后合并在一起。

Dim m As System.IO.MemoryStream = PDFHelper.fillPDF(filename, New Dictionary(Of String, String), New List(Of PDFHelper.PDfImage), "SAMPLE") 
Dim data As Byte() = m.GetBuffer 
Response.Clear() 

//Send the file to the output stream 
Response.Buffer = True 

//Try and ensure the browser always opens the file and doesn’t just prompt to “open/save”. 
Response.AddHeader("Content-Length", data.Length.ToString()) 
Response.AddHeader("Content-Disposition", "inline; filename=" + "Sample") 
Response.AddHeader("Expires", "0") 
Response.AddHeader("Pragma", "cache") 
Response.AddHeader("Cache-Control", "private") 

//Set the output stream to the correct content type (PDF). 
Response.ContentType = "application/pdf" 
Response.AddHeader("Accept-Ranges", "bytes") 

//Output the file 
Response.BinaryWrite(data) 

//Flushing the Response to display the serialized data to the client browser. 
Response.Flush() 

Try 
    Response.End() 
Catch ex As Exception 
    Throw ex 
End Try 

下面是函数在我的公用事业类(PDFHelper.fillPDF)

Public Shared Function fillPDF(fileToFill As String, Optional fieldValues As Dictionary(Of String, String) = Nothing, Optional images As List(Of PDfImage) = Nothing, Optional watermarkText As String = "") As MemoryStream 

     Dim m As MemoryStream = New MemoryStream() // for storing the pdf 
     Dim reader As PdfReader = New PdfReader(fileToFill) // for reading the document 
     Dim outStamper As PdfStamper = New PdfStamper(reader, m) //for filling the document 

     If fieldValues IsNot Nothing Then 
      For Each kvp As KeyValuePair(Of String, String) In fieldValues 
       outStamper.AcroFields.SetField(kvp.Key, kvp.Value) 
      Next 
     End If 


     If images IsNot Nothing AndAlso images.Count > 0 Then //add all the images 

      For Each PDfImage In images 
       Dim img As iTextSharp.text.Image = Nothing //image to stamp 

       //set up the image (different for different cases 
       Select Case PDfImage.ImageType 
        //removed for brevity 
       End Select 

       Dim overContent As PdfContentByte = outStamper.GetOverContent(PDfImage.PageNumber) // specify page number for stamping 
       overContent.AddImage(img) 

      Next 

     End If 

     //add the water mark 
     If watermarkText <> "" Then 
      Dim underContent As iTextSharp.text.pdf.PdfContentByte = Nothing 
      Dim watermarkRect As iTextSharp.text.Rectangle = reader.GetPageSizeWithRotation(1) 

      //removed for brevity 
     End If 

     //flatten and close out 
     outStamper.FormFlattening = True 
     outStamper.SetFullCompression() 
     outStamper.Close() 
     reader.Close() 
     Return m 

回答

3

由于你的代码正在以流的PDF,一个简单的方法来解决你的问题是使一个小的变化,以您的fillPDF方法 - 有它返回一个字节数组:

// other parameters left out for simplicity sake 
public static byte[] fillPDF(string resource) { 
    PdfReader reader = new PdfReader(resource); 
    using (var ms = new MemoryStream()) { 
    using (PdfStamper stamper = new PdfStamper(reader, ms)) { 
     // do whatever you need to do 
    } 
    return ms.ToArray(); 
    }  
} 

然后你可以流的字节数组客户在ASP.NET 将其保存到文件系统:

// get the manipulated PDF  
byte[] myPdf = fillPDF(inputFile); 
// stream via ASP.NET 
Response.BinaryWrite(myPdf); 
// save to file system 
File.WriteAllBytes(outputFile, myPdf); 

如果你从一个ST生成PDF在编写PDF之后,不要忘记调用Response.End(),否则字节数组最后会附加HTML标记垃圾。

+0

今天我会试试这个。谢谢! – user158017

+0

这不是“完美”的答案,但我接受它,因为它使我找到了正确的解决方案。我的问题是,我没有意识到MemoryStream.GetBuffer和MemoryStream.ToArray之间的不同。根据你的代码,我检查了这个文档:http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer.aspx,并意识到GetBuffer包含了无关的字节。我切换到File.WriteAllBytes(outputFile,m.ToArray),它工作完美!谢谢。 – user158017

0

这将现有的PDF复制到MemoryStream,然后将其保存到磁盘。也许你可以适应它来解决你的问题?

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 
    Dim strInputFilename As String = "C:\Junk\Junk.pdf" 
    Dim strOutputFilename As String = "C:\Junk\Junk2.pdf" 
    Dim byt() As Byte 
    Using ms As New MemoryStream 
     '1. Load PDF into memory stream' 
     Using bw As New BinaryWriter(ms) 
     Using fsi As New FileStream(strInputFilename, FileMode.Open) 
      Using br As New BinaryReader(fsi) 
      Try 
       Do 
       bw.Write(br.ReadByte()) 
       Loop 
      Catch ex As EndOfStreamException 
      End Try 
      End Using 
     End Using 
     End Using 
     byt = ms.ToArray() 
    End Using 
    '2. Write memory copy of PDF back to disk' 
    My.Computer.FileSystem.WriteAllBytes(strOutputFilename, byt, False) 
    Process.Start(strOutputFilename) 
    End Sub