2010-11-19 6 views
7

Utilizzando itextsharp (o qualsiasi libreria pdf C#), ho bisogno di aprire un PDF, sostituire un testo segnaposto con valori effettivi e restituirlo come un byte [].Usando itextsharp (o qualsiasi libreria pdf C#), come aprire un PDF, sostituire del testo e salvarlo di nuovo?

Qualcuno può suggerire come farlo? Ho dato un'occhiata ai documenti di itext e non riesco a capire dove iniziare. Finora sono rimasto bloccato su come ottenere il pdf sorgente da un PDFReader a un oggetto Document, presumo che probabilmente mi sto avvicinando a questo nel modo sbagliato.

Grazie mille

+0

trovato questo finora: http://www.johnnycode.com/blog/2010/03/05/using-a-template-to-programmatically-create-pdfs-with-c -e-itextsharp/ – Chris

risposta

5

Alla fine, ho usato PDFescape di aprire il mio file PDF esistente, e posizionare alcuni campi del modulo in cui ho bisogno di mettere i miei campi, quindi salvarlo di nuovo per creare il mio file PDF.

http://www.pdfescape.com

poi ho trovato questo blog su come sostituire i campi del modulo:

http://www.johnnycode.com/blog/2010/03/05/using-a-template-to-programmatically-create-pdfs-with-c-and-itextsharp/

Tutto funziona bene! Ecco il codice:

public static byte[] Generate() 
{ 
    var templatePath = HttpContext.Current.Server.MapPath("~/my_template.pdf"); 

    // Based on: 
    // http://www.johnnycode.com/blog/2010/03/05/using-a-template-to-programmatically-create-pdfs-with-c-and-itextsharp/ 
    var reader = new PdfReader(templatePath); 
    var outStream = new MemoryStream(); 
    var stamper = new PdfStamper(reader, outStream); 

    var form = stamper.AcroFields; 
    var fieldKeys = form.Fields.Keys; 

    foreach (string fieldKey in fieldKeys) 
    { 
    if (form.GetField(fieldKey) == "MyTemplatesOriginalTextFieldA") 
     form.SetField(fieldKey, "1234"); 
    if (form.GetField(fieldKey) == "MyTemplatesOriginalTextFieldB") 
     form.SetField(fieldKey, "5678"); 
    } 

    // "Flatten" the form so it wont be editable/usable anymore 
    stamper.FormFlattening = true; 

    stamper.Close(); 
    reader.Close(); 

    return outStream.ToArray(); 
} 
+0

Non penso che sia necessario utilizzare i tasti di campo, è possibile utilizzare: form.SetField ("MyTemplatesOriginalTextFieldA", "1234"); e così via. – Lachlan

+0

Ah sì, sarebbe il modo in cui lo sto facendo ora. – Chris

+0

Indietro quando ho scritto quel codice, era così perché stavo sostituendo il valore reale nei campi (senza nome), invece di dare i campi e nominarli, come suggerisci correttamente è l'opzione migliore. – Chris

1

Purtroppo stavo cercando qualcosa di simile e non riuscivano a capirlo. Qui di seguito è stato circa quanto ho ottenuto, forse è possibile utilizzare questo come punto di partenza. Il problema è che PDF in realtà non salva il testo, ma utilizza invece tabelle di ricerca e qualche altra magica arcana. Questo metodo legge i valori di byte per la pagina e tenta di convertire in stringa, ma per quanto posso dire può solo fare l'inglese e perdere su alcuni caratteri speciali, così ho abbandonato il mio progetto e sono andato avanti.

string contents = string.Empty(); 
Document doc = new Document(); 
PdfReader reader = new PdfReader("pathToPdf.pdf"); 
using (MemoryStream memoryStream = new MemoryStream()) 
{ 

    PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream); 
    doc.Open(); 
    PdfContentByte cb = writer.DirectContent; 
    for (int p = 1; p <= reader.NumberOfPages; p++) 
    { 
     // add page from reader 
     doc.SetPageSize(reader.GetPageSize(p)); 
     doc.NewPage(); 

     // pickup here something like this: 
     byte[] bt = reader.GetPageContent(p); 
     contents = ExtractTextFromPDFBytes(bt); 

     if (contents.IndexOf("something")!=-1) 
     { 
      // make your own pdf page and add to cb (contentbyte) 

     } 
     else 
     { 
      PdfImportedPage page = writer.GetImportedPage(reader, p); 
      int rot = reader.GetPageRotation(p); 
      if (rot == 90 || rot == 270) 
       cb.AddTemplate(page, 0, -1.0F, 1.0F, 0, 0, reader.GetPageSizeWithRotation(p).Height); 
      else 
       cb.AddTemplate(page, 1.0F, 0, 0, 1.0F, 0, 0); 
     } 
    } 
    reader.Close(); 
    doc.Close(); 
    File.WriteAllBytes("pathToOutputOrSamePathToOverwrite.pdf", memoryStream.ToArray()); 

Questo è preso da this site.

private string ExtractTextFromPDFBytes(byte[] input) 
{ 
    if (input == null || input.Length == 0) return ""; 

    try 
    { 
     string resultString = ""; 

     // Flag showing if we are we currently inside a text object 
     bool inTextObject = false; 

     // Flag showing if the next character is literal 
     // e.g. '\\' to get a '\' character or '\(' to get '(' 
     bool nextLiteral = false; 

     //() Bracket nesting level. Text appears inside() 
     int bracketDepth = 0; 

     // Keep previous chars to get extract numbers etc.: 
     char[] previousCharacters = new char[_numberOfCharsToKeep]; 
     for (int j = 0; j < _numberOfCharsToKeep; j++) previousCharacters[j] = ' '; 


      for (int i = 0; i < input.Length; i++) 
      { 
       char c = (char)input[i]; 

       if (inTextObject) 
       { 
        // Position the text 
        if (bracketDepth == 0) 
        { 
         if (CheckToken(new string[] { "TD", "Td" }, previousCharacters)) 
         { 
          resultString += "\n\r"; 
         } 
         else 
         { 
          if (CheckToken(new string[] { "'", "T*", "\"" }, previousCharacters)) 
          { 
           resultString += "\n"; 
          } 
          else 
          { 
           if (CheckToken(new string[] { "Tj" }, previousCharacters)) 
           { 
            resultString += " "; 
           } 
          } 
         } 
        } 

        // End of a text object, also go to a new line. 
        if (bracketDepth == 0 && 
         CheckToken(new string[] { "ET" }, previousCharacters)) 
        { 

         inTextObject = false; 
         resultString += " "; 
        } 
        else 
        { 
         // Start outputting text 
         if ((c == '(') && (bracketDepth == 0) && (!nextLiteral)) 
         { 
          bracketDepth = 1; 
         } 
         else 
         { 
          // Stop outputting text 
          if ((c == ')') && (bracketDepth == 1) && (!nextLiteral)) 
          { 
           bracketDepth = 0; 
          } 
          else 
          { 
           // Just a normal text character: 
           if (bracketDepth == 1) 
           { 
            // Only print out next character no matter what. 
            // Do not interpret. 
            if (c == '\\' && !nextLiteral) 
            { 
             nextLiteral = true; 
            } 
            else 
            { 
             if (((c >= ' ') && (c <= '~')) || 
              ((c >= 128) && (c < 255))) 
             { 
              resultString += c.ToString(); 
             } 

             nextLiteral = false; 
            } 
           } 
          } 
         } 
        } 
       } 

       // Store the recent characters for 
       // when we have to go back for a checking 
       for (int j = 0; j < _numberOfCharsToKeep - 1; j++) 
       { 
        previousCharacters[j] = previousCharacters[j + 1]; 
       } 
       previousCharacters[_numberOfCharsToKeep - 1] = c; 

       // Start of a text object 
       if (!inTextObject && CheckToken(new string[] { "BT" }, previousCharacters)) 
       { 
        inTextObject = true; 
       } 
      } 
     return resultString; 
    } 
    catch 
    { 
     return ""; 
    } 
} 

private bool CheckToken(string[] tokens, char[] recent) 
{ 
    foreach (string token in tokens) 
    { 
     if ((recent[_numberOfCharsToKeep - 3] == token[0]) && 
      (recent[_numberOfCharsToKeep - 2] == token[1]) && 
      ((recent[_numberOfCharsToKeep - 1] == ' ') || 
      (recent[_numberOfCharsToKeep - 1] == 0x0d) || 
      (recent[_numberOfCharsToKeep - 1] == 0x0a)) && 
      ((recent[_numberOfCharsToKeep - 4] == ' ') || 
      (recent[_numberOfCharsToKeep - 4] == 0x0d) || 
      (recent[_numberOfCharsToKeep - 4] == 0x0a))) 
      { 
       return true; 
      } 
    } 
    return false; 
} 
+0

cosa manca a '_numberOfCharsToKeep' per dichiarare questo.so guidami come definirlo. –