0

我正在尝试将带有 id 的图像插入 PDF 文档,并允许稍后用另一个图像替换它。我的流程如下:

  1. 从客户端获取图像(具有唯一 ID)。
  2. 尝试在 PDF 文档中查找具有相同 ID 的现有图像。
  3. 如果我找到现有图像,请尝试将其删除并放置新图像,或者尝试用新图像替换现有图像。(都试过了)。
  4. 如果我没有找到现有图像,请将图像插入我选择的位置。

我使用 Bruno Lowagie 书中的代码:

问题是每当我删除现有图像或替换它时,我的文档都会损坏。我究竟做错了什么?这是代码:

public static bool PdfInsertSignature(string path, string fileName, string signatureName, byte[] imageBytes)
{
    bool resultOk = true;
    string tmpFilename = string.Concat("tmp_", Guid.NewGuid().ToString(), ".pdf");
    // get file, copy to new file with signature
    using (Stream inputPdfStream = new FileStream(path + fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
    using (Stream outputPdfStream = new FileStream(path + tmpFilename, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        using (var reader = new PdfReader(inputPdfStream))
        using (PdfStamper stamper = new PdfStamper(reader, outputPdfStream, '\0', false))
        {
            var img = System.Drawing.Image.FromStream(new MemoryStream(imageBytes));
            Image image = Image.GetInstance(img, BaseColor.WHITE);
            img.Dispose();
            var positions = stamper.AcroFields.GetFieldPositions(signatureName)[0];

            if (positions != null)
            {
                //DeleteExistingSignatureImage(reader, stamper, signatureName);

                image.SetAbsolutePosition(positions.position.Left + 20, positions.position.Top - 15);
                image.ScalePercent(0.2f * 100);
                image.BorderWidth = 0;

                PdfImage pdfImg = new PdfImage(image, "", null);
                pdfImg.Put(new PdfName("ITXT_SigImageId"), new PdfName(signatureName + "_img"));

                if (!ReplaceImage(reader, stamper, signatureName, pdfImg))
                {
                    PdfIndirectObject objRef = stamper.Writer.AddToBody(pdfImg);
                    image.DirectReference = objRef.IndirectReference;
                    PdfContentByte pdfContentByte = stamper.GetOverContent(positions.page);
                    pdfContentByte.AddImage(image);
                }                        
            }
            else
            {
                resultOk = false;
                logger.Error($"No matching Signature found for signatureName: {signatureName} in fileName: {fileName}.");
            }
        }
    }

    if (resultOk)
    {
        // delete old file and rename new file to old file's name
        File.Delete(path + fileName);
        File.Move(path + tmpFilename, path + fileName);
    }
    else
    {
        File.Delete(path + tmpFilename);
    }

    return resultOk;
}

private static bool ReplaceImage(PdfReader reader, PdfStamper stamper, string signatureName, PdfStream newImgStream)
{
    PdfName key = new PdfName("ITXT_SigImageId");
    PdfName value = new PdfName(signatureName + "_img");
    PdfObject obj;
    PRStream stream;

    for (int i = 1; i < reader.XrefSize; i++)
    {
        obj = reader.GetPdfObject(i);
        if (obj == null || !obj.IsStream())
        {
            continue;
        }
        stream = (PRStream)obj;
        PdfObject pdfSubtype = stream.Get(PdfName.SUBTYPE);

        if (pdfSubtype != null && pdfSubtype.ToString().Equals(PdfName.IMAGE.ToString()))
        {
            var streamVal = stream.Get(key);
            if (streamVal != null && value.Equals(streamVal))
            {
                stream.Clear();
                var ms = new MemoryStream();
                stream.WriteContent(ms);
                stream.SetData(ms.ToArray(), false);

                foreach (PdfName name in newImgStream.Keys)
                {
                    stream.Put(name, stream.Get(name));
                }

                return true;
            }
        }
    }

    return false;
}

private static void DeleteExistingSignatureImage(PdfReader reader, PdfStamper stamper, string signatureName)
{
    PdfName key = new PdfName("ITXT_SigImageId");
    PdfName value = new PdfName(signatureName + "_img");
    PdfObject obj;
    PRStream stream;

    for (int i = 1; i < reader.XrefSize; i++)
    {
        obj = reader.GetPdfObject(i);
        if (obj == null || !obj.IsStream())
        {
            continue;
        }
        stream = (PRStream)obj;
        PdfObject pdfSubtype = stream.Get(PdfName.SUBTYPE);

        if (pdfSubtype != null && pdfSubtype.ToString().Equals(PdfName.IMAGE.ToString()))
        {
            var streamVal = stream.Get(key);
            if (streamVal != null && value.Equals(streamVal))
            {
                stream.Clear();
                PdfReader.KillIndirect(stream);
                //PdfReader.KillIndirect(obj);
                //reader.RemoveUnusedObjects();
            }
        }
    }
}
4

2 回答 2

1

签署 PDF 文件的目的是为了防止进一步更改,恕不另行通知。交换图像后,您需要在文档上签名,否则会损坏。

只是让它更容易找到: 是 amira 提供的解决方案。

于 2019-04-17T11:25:29.027 回答
0

这是我用来用签名图像替换 PDF 模板上的“ButtonField”的代码:

string TempStampPath = Server.MapPath(TempPath + "BookingConfirmation.pdf");
            PdfReader pdfReader = new PdfReader(TempStampPath);
            PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(LocalFileName, FileMode.Create));
            AcroFields pdfFormFields = pdfStamper.AcroFields;
            try
            {
                pdfFormFields.SetField("NameSurname", NameSurname);
                pdfFormFields.SetField("IdNumber", IDNumber);
                pdfFormFields.SetField("CourseName", CourseName);
                pdfFormFields.SetField("Location", Venue);
                pdfFormFields.SetField("DateCompleted", CourseDate);
                pdfFormFields.SetField("FacilitatorName", Facilitator);

                try
                {
                    iTextSharp.text.Image signature = iTextSharp.text.Image.GetInstance(image, System.Drawing.Imaging.ImageFormat.Png);

                    PushbuttonField ad = pdfStamper.AcroFields.GetNewPushbuttonFromField("btnFacilitatorSignature");
                    ad.Layout = PushbuttonField.LAYOUT_ICON_ONLY;
                    ad.ProportionalIcon = true;
                    ad.Image = signature;
                    ad.BackgroundColor = iTextSharp.text.BaseColor.WHITE;
                    pdfFormFields.ReplacePushbuttonField("btnFacilitatorSignature", ad.Field);
                }
                catch (Exception ex)
                { }

                pdfStamper.FormFlattening = true;
                pdfStamper.Close();
                pdfStamper.Dispose();
                pdfReader.Close();
            }
            catch (Exception ex)
            {
                pdfStamper.Close();
                pdfStamper.Dispose();
                pdfReader.Close();
            }
于 2020-05-07T06:32:35.427 回答