2

私はVB.NetでiTextSharpを使用して、PDFドキュメントに画像をスタンプしています。(これは言語固有ではないため、C#のタグも付けました。)このプロセスを使用するアプリケーションが2つあります。

  • 1つ目は、メモリストリームのバイトを使用してPDFドキュメントをオンラインで表示します。この作品は機能しています。

  • 2つ目は同じ機能を使用しますが、代わりにPDFをファイルに保存します。この部分は無効なPDFを生成します。

私はいくつかの同様の質問を見ましたが、それらはすべて最初にドキュメントを作成していて、コードにドキュメントオブジェクトがあります。それらのメモリストリームは最初から破損しています。コードにドキュメントオブジェクトがなく、元のメモリストリームが正常に開きます。

エラーが発生する場所は次のとおりです(fillPDF関数のスタンパーは、特にマークされていない限り、デフォルトでストリームを閉じるため、mからのバッファーを新しいメモリストリームに配置する必要があります。)

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()

これが私がウェブサイトでそれをうまく使う方法の1つです。これは画像を使用しませんが、他の同様の成功した場所のいくつかは、複数のドキュメントの画像を使用し、それらが一緒にマージされます。

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
4

2 に答える 2

4

コードはPDFをストリーミングするように機能しているため、問題を修正する簡単な方法の1つは、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);

標準のASP.NETWebフォームからPDFを生成している場合は、PDFの書き込みResponse.End()後に呼び出すことを忘れないでください。そうしないと、バイト配列の最後にHTMLマークアップのガベージが追加されます。

于 2012-06-06T10:45:29.243 に答える
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
于 2012-06-06T02:56:19.240 に答える