【问题标题】:Is there a way to edit a pdf with C# .net core?有没有办法用 C# .net core 编辑 pdf?
【发布时间】:2020-10-29 18:40:15
【问题描述】:

我想知道是否有任何方法可以使用 c# .net core 编辑 pdf,只是为了替换一些单词

【问题讨论】:

  • PDF 不是为编辑而设计的。你能得到的最好的方法是在现有文本上绘画。现有文本不重排,由您来匹配字体并与现有文本对齐

标签: .net pdf .net-core .net-standard


【解决方案1】:

aspose.pdf 是一款商业产品,可为您提供适用于 .NET Framework、.NET Core、Java 和 C++ 的此功能

【讨论】:

    【解决方案2】:

    我刚刚找到了这个 nuget 包sautinsoft.document

    为了替换这个词,他们在their documentation中有一个例子:

    using System.IO;
    using SautinSoft.Document;
    using System.Linq;
    using System.Text.RegularExpressions;
    
    namespace Sample
    {
        class Sample
        {
    
            static void Main(string[] args)
            {
                FindAndReplace();
            }
    
            /// <summary>
            /// Find and replace a text using ContentRange.
            /// </summary>
            /// <remarks>
            /// Details: https://sautinsoft.com/products/document/examples/find-replace-content-net-csharp-vb.php
            /// </remarks>
            public static void FindAndReplace()
            {
                // Path to a loadable document.
                string loadPath = @"..\..\critique.pdf";
    
                // Load a document intoDocumentCore.
                DocumentCore dc = DocumentCore.Load(loadPath);
    
                Regex regex = new Regex(@"bean", RegexOptions.IgnoreCase);
    
                //Find "Bean" and Replace everywhere on "Joker :-)"
                // Please note, Reverse() makes sure that action replace not affects to Find().
                foreach (ContentRange item in dc.Content.Find(regex).Reverse())
                {
                    item.Replace("Joker");
                }
    
                // Save our document into PDF format.
                string savePath = "Replaced.pdf";
                dc.Save(savePath, new PdfSaveOptions());
    
                // Open the result for demonstration purposes.
                System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(loadPath) { UseShellExecute = true });
                System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(savePath) { UseShellExecute = true });
            }
        }
    }
    

    真的很简单:)

    【讨论】:

    • 此示例更改 DOCX 文档中的文本,而不是 PDF。
    • 我会编辑我的答案,逻辑完全一样。我在我的应用程序中对其进行了测试,效果很好。
    • 我用旧的简单 test document 对此进行了测试,将“Test”或“Dokument”替换为“Überprüfung”或“stet”。实际上,它替换了文本 but 在每种情况下它都用完全不同的字体替换了字体。由于字体仅是嵌入的子集,因此使用不同字体替换“Überprüfung”是可以接受的。但是,当替换为“stet”时,原始字体中的所有字形都存在,因此此处无法解释切换字体。
    • 因此,在某些情况下,这种替换基本上可以正常工作,但必须注意,即使在实际更改的内容范围之外,它也会引入不需要的更改。对于生产用途,这意味着它可以用于受控输入(例如,用于针对此例程测试的许多 PDF 生成器的文档),但不能用于任意输入文档(例如,用户不受控制的上传)。
    【解决方案3】:

    Docotic.Pdf library 提供了两种替换页面上静态文本的选项:

    1. 复制页面对象并更改特定的文本块。基本样本: https://github.com/BitMiracle/Docotic.Pdf.Samples/tree/master/Samples/Pages%20and%20Navigation/CopyPageObjects

      drawText 方法中,您可以检查 PdfTextData.Text 值并改为绘制另一个文本(替换 target.DrawString(td.GetCharacterCodes()); 调用)

      例如,此代码将第一页上所有出现的“have”替换为“has”:

      using System.Diagnostics;
      
      namespace BitMiracle.Docotic.Pdf.Samples
      {
          public static class CopyPageObjects
          {
              public static void Main()
              {
                  // NOTE: 
                  // When used in trial mode, the library imposes some restrictions.
                  // Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx
                  // for more information.
      
                  const string PathToFile = "CopyPageObjects.pdf";
      
                  using (var pdf = new PdfDocument(@"C:\Work\BitMiracle\Docotic\QPdf\Futura_font.pdf"))
                  {
                      using (PdfDocument copy = pdf.CopyPages(0, 1))
                      {
                          PdfPage sourcePage = copy.Pages[0];
                          PdfPage copyPage = copy.AddPage();
      
                          copyPage.Rotation = sourcePage.Rotation;
                          copyPage.MediaBox = sourcePage.MediaBox;
                          if (sourcePage.CropBox != sourcePage.MediaBox)
                              copyPage.CropBox = sourcePage.CropBox;
      
                          PdfCanvas target = copyPage.Canvas;
                          foreach (PdfPageObject obj in sourcePage.GetObjects())
                          {
                              target.SaveState();
                              setClipRegion(target, obj.ClipRegion);
      
                              if (obj.Type == PdfPageObjectType.Path)
                              {
                                  PdfPath path = (PdfPath)obj;
                                  target.Transform(path.TransformationMatrix);
      
                                  if (path.PaintMode == PdfDrawMode.Fill || path.PaintMode == PdfDrawMode.FillAndStroke)
                                      setBrush(target.Brush, path.Brush);
      
                                  if (path.PaintMode == PdfDrawMode.Stroke || path.PaintMode == PdfDrawMode.FillAndStroke)
                                      setPen(target.Pen, path.Pen);
      
                                  appendPath(target, path);
                                  drawPath(target, path);
                              }
                              else if (obj.Type == PdfPageObjectType.Image)
                              {
                                  PdfPaintedImage image = (PdfPaintedImage)obj;
                                  target.TranslateTransform(image.Position.X, image.Position.Y);
                                  target.Transform(image.TransformationMatrix);
      
                                  setBrush(target.Brush, image.Brush);
                                  target.DrawImage(image.Image, 0, 0, 0);
                              }
                              else if (obj.Type == PdfPageObjectType.Text)
                              {
                                  PdfTextData text = (PdfTextData)obj;
                                  drawText(target, text);
                              }
      
                              target.RestoreState();
                          }
      
                          copy.RemovePage(0);
      
                          copy.Save(PathToFile);
                      }
                  }
      
                  Process.Start(PathToFile);
              }
      
              private static void setClipRegion(PdfCanvas canvas, PdfClipRegion clipRegion)
              {
                  if (clipRegion.IntersectedPaths.Count == 0)
                      return;
      
                  PdfMatrix transformationBefore = canvas.TransformationMatrix;
                  try
                  {
                      foreach (PdfPath clipPath in clipRegion.IntersectedPaths)
                      {
                          canvas.ResetTransform();
                          canvas.Transform(clipPath.TransformationMatrix);
                          appendPath(canvas, clipPath);
                          canvas.SetClip(clipPath.ClipMode.Value);
                      }
                  }
                  finally
                  {
                      canvas.ResetTransform();
                      canvas.Transform(transformationBefore);
                  }
              }
      
              private static void setBrush(PdfBrush dst, PdfBrushInfo src)
              {
                  PdfColor color = src.Color;
                  if (color != null)
                      dst.Color = color;
      
                  dst.Opacity = src.Opacity;
      
                  var pattern = src.Pattern;
                  if (pattern != null)
                      dst.Pattern = pattern;
              }
      
              private static void setPen(PdfPen dst, PdfPenInfo src)
              {
                  PdfColor color = src.Color;
                  if (color != null)
                      dst.Color = color;
      
                  var pattern = src.Pattern;
                  if (pattern != null)
                      dst.Pattern = pattern;
      
                  dst.DashPattern = src.DashPattern;
                  dst.EndCap = src.EndCap;
                  dst.LineJoin = src.LineJoin;
                  dst.MiterLimit = src.MiterLimit;
                  dst.Opacity = src.Opacity;
                  dst.Width = src.Width;
              }
      
              private static void appendPath(PdfCanvas target, PdfPath path)
              {
                  foreach (PdfSubpath subpath in path.Subpaths)
                  {
                      foreach (PdfPathSegment segment in subpath.Segments)
                      {
                          switch (segment.Type)
                          {
                              case PdfPathSegmentType.Point:
                                  target.CurrentPosition = ((PdfPointSegment)segment).Value;
                                  break;
      
                              case PdfPathSegmentType.Line:
                                  PdfLineSegment line = (PdfLineSegment)segment;
                                  target.CurrentPosition = line.Start;
                                  target.AppendLineTo(line.End);
                                  break;
      
                              case PdfPathSegmentType.Bezier:
                                  PdfBezierSegment bezier = (PdfBezierSegment)segment;
                                  target.CurrentPosition = bezier.Start;
                                  target.AppendCurveTo(bezier.FirstControl, bezier.SecondControl, bezier.End);
                                  break;
      
                              case PdfPathSegmentType.Rectangle:
                                  target.AppendRectangle(((PdfRectangleSegment)segment).Bounds);
                                  break;
      
                              case PdfPathSegmentType.CloseSubpath:
                                  target.ClosePath();
                                  break;
                          }
                      }
                  }
              }
      
              private static void drawPath(PdfCanvas target, PdfPath path)
              {
                  switch (path.PaintMode)
                  {
                      case PdfDrawMode.Fill:
                          target.FillPath(path.FillMode.Value);
                          break;
      
                      case PdfDrawMode.FillAndStroke:
                          target.FillAndStrokePath(path.FillMode.Value);
                          break;
      
                      case PdfDrawMode.Stroke:
                          target.StrokePath();
                          break;
      
                      default:
                          target.ResetPath();
                          break;
                  }
              }
      
              private static void drawText(PdfCanvas target, PdfTextData td)
              {
                  target.TextRenderingMode = td.RenderingMode;
                  setBrush(target.Brush, td.Brush);
                  setPen(target.Pen, td.Pen);
      
                  target.TextPosition = PdfPoint.Empty;
                  target.FontSize = td.FontSize;
                  target.Font = td.Font;
                  target.CharacterSpacing = td.CharacterSpacing;
                  target.WordSpacing = td.WordSpacing;
                  target.TextHorizontalScaling = td.HorizontalScaling;
      
                  target.TranslateTransform(td.Position.X, td.Position.Y);
                  target.Transform(td.TransformationMatrix);
      
                  if (!td.Text.Contains("have"))
                      target.DrawString(td.GetCharacterCodes());
                  else
                      target.DrawString(td.Text.Replace("have", "has"));
              }
          }
      }
      
    2. 隐藏现有文本块并在上方绘制新文本。 您可以尝试在没有边框的只读文本框中绘制新文本:

      using (PdfDocument pdf = ..)
      {
          // "replace" text - hide existing text and draw a new one.
          PdfPage page = pdf.Pages[0];
          PdfCanvas canvas = page.Canvas;
          foreach (PdfTextData word in page.GetWords())
          {
              if (word.Text == "text_to_replace")
              {
                  PdfRectangle rectangleToHide = word.Bounds;
      
                  canvas.Brush.Color = new PdfRgbColor(255, 255, 255);
                  canvas.DrawRectangle(rectangleToHide, PdfDrawMode.Fill);
      
                  // Draw new string in a readonly text box. This solution restricts selection of the old string.
                  PdfTextBox textBox = page.AddTextBox(rectangleToHide);
                  textBox.HasBorder = false;
                  textBox.ReadOnly = true;
                  textBox.Font = word.Font;
                  textBox.FontSize = word.FontSize * word.TransformationMatrix.M22;
                  textBox.Text = "new text";
              }
          }
      
          pdf.Save(..);
      }
      

    【讨论】:

      猜你喜欢
      • 2011-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 2017-05-02
      • 1970-01-01
      • 1970-01-01
      • 2012-08-20
      相关资源
      最近更新 更多