2012-06-05 53 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