查找 PDF 表单字段位置

Find PDF Form Field position

我知道这个问题已经被问了很多,但我找不到任何关于如何在 RoR 中执行此操作的信息。我正在使用 pdf-forms but this does not support adding images, and I need to be able to add an image of a customer's signature into the PDF. I have used prawn 使用表单文本字段填充 PDF 以在现有 PDF 上呈现图像,但我需要知道在签名行上添加图像的确切位置。所以我的问题是如何查看任意 PDF 并找到 "Signature" 表单字段的确切位置?

您可以使用这个 gem 'wicked_pdf。你随便写html,这个gem自动转成pdf 阅读更多 https://github.com/mileszs/wicked_pdf

我最终使用 pdf2json 找到表单域的 x,y 位置。我使用以下命令生成原始 pdf 的 JSON 文件:

%x{ pdf2json -f "#{form_path}" }

JSON 文件生成在与form_path 相同的目录中。我使用这些命令找到了我想要的字段:

jsonObj = JSON.parse(File.read(json_path))
signature_fields = jsonObj["formImage"]["Pages"].first["Fields"].find_all do |f|
    f["id"]["Id"] == 'signature'
end

我可以使用 prawn to first create a new PDF with the image. Then using pdf-forms,我 multistamp 将图像 pdf 放到我想添加图像的原始 PDF 上。但是 multistamp applies each page of the stamp PDF to the corresponding page of the input PDF 所以请确保您的图像 PDF 具有正确的页数,否则您的图像将被标记在每一页上。我只想将图片印在首页,所以我执行以下操作:

  num_pages = %x{ #{Rails.configuration.pdftk_path} #{form_path} dump_data | grep "NumberOfPages" | cut -d":" -f2 }.to_i
  signaturePDF = "/tmp/signature.pdf"
  Prawn::Document.generate(signaturePDF) do
    signature_fields.each do |field|
      image Rails.root.join("signature.png"), at: [field["x"], field["y"]], 
                                                  width: 50
    end
    [0...num_pages - 1].each{|p| start_new_page }
  end

  outputPDF = "/tmp/output.pdf"
  pdftk.multistamp originalPDF, signaturePDF, outputPDF

这是一个纯 ruby 实现,它将使用 Origami return 字段的名称、页面、x、y、高度和宽度 https://github.com/gdelugre/origami

require "origami"

def pdf_field_metadata(file_path)
  pdf = Origami::PDF.read file_path

  field_to_page = {}
  pdf.pages.each_with_index do |page, page_index|
    (page.Annots || []).each do |annot|
      field_to_page[annot.refno] = page_index
    end
  end

  field_metas = []
  pdf.fields.each do |field|
    field_metas << {
      name: field.T,
      page_index: field_to_page[field.no],
      x: field.Rect[0].to_f,
      y: field.Rect[1].to_f,
      h: field.Rect[3].to_f - field.Rect[1],
      w: field.Rect[2].to_f - field.Rect[0]
    }
  end

  field_metas
end

pdf_field_metadata "<path to pdf>"

我还没有对它进行特别彻底的测试,但希望这段代码可以帮助您完成大部分工作。

另外——请记住,上面计算的坐标是从 pdf 页面的左下角开始计算的,而不是从右上角开始计算的(并且不是以像素为单位)。我相信每英寸总是有 72 点,您可以通过在上面的 pdf.pages 循环中调用 page.MediaBox 来获得总页数。如果您要查找像素坐标,则需要知道生成的渲染文档的 DPI。