2010-11-19 8 views
7

En utilisant itextsharp (ou toute autre bibliothèque C# pdf), j'ai besoin d'ouvrir un fichier PDF, de remplacer un texte d'espace réservé par des valeurs réelles et de le renvoyer sous la forme d'un octet [].En utilisant itextsharp (ou une bibliothèque C# pdf), comment ouvrir un PDF, remplacer du texte et le sauvegarder à nouveau?

Quelqu'un peut-il suggérer comment faire cela? J'ai regardé les docs itext et je ne sais pas par où commencer. Jusqu'à présent, je suis bloqué sur la façon d'obtenir le pdf source à partir d'un PDFReader à un objet Document, je présume que je suis probablement en train d'aborder ce problème dans le mauvais sens.

Merci beaucoup

+0

Trouvé ce jusqu'à présent: http://www.johnnycode.com/blog/2010/03/05/using-a-template-to-programmatically-create-pdfs-with-c -and-itextsharp/ – Chris

Répondre

5

pour créer mon fichier PDF.

http://www.pdfescape.com

Alors je trouve cette entrée de blog sur la façon de remplacer les champs de formulaire:

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

Tout fonctionne bien! Voici le code:

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

Je ne pense pas que vous devez utiliser les touches de champ - vous pouvez utiliser à la place: form.SetField ("MyTemplatesOriginalTextFieldA", "1234"); et ainsi de suite. – Lachlan

+0

Ah oui, ce serait comme ça que je le fais maintenant. – Chris

+0

Lorsque j'ai écrit ce code, c'était comme ça parce que je remplaçais la valeur réelle dans les champs (sans nom), au lieu de donner les champs et de les nommer, comme vous le suggérez, est la meilleure option. – Chris

1

Malheureusement, je cherchais quelque chose de similaire et ne pouvait pas comprendre. Ci-dessous était à propos de ce que j'ai obtenu, peut-être que vous pouvez utiliser cela comme point de départ. Le problème est que PDF ne sauvegarde pas le texte, mais utilise plutôt des tables de recherche et d'autres magies arcanes. Cette méthode lit les octets de la page et tente de la convertir en chaîne, mais pour autant que je sache, elle ne peut que faire l'anglais et manque des caractères spéciaux, alors j'ai abandonné mon projet et je suis passé à autre chose.

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

Ceci est tiré de this site. En fin de compte, j'ai utilisé PDFescape pour ouvrir mon fichier PDF existant, et placer des champs de formulaire dans où je dois mettre mes champs, puis enregistrez-le à nouveau

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

ce qui est '_numberOfCharsToKeep' manquant pour déclarer ceci.so me guider comment définir ceci. –

Questions connexes