Извлечение имен полей формы PDF из формы PDF - PullRequest
21 голосов
/ 24 января 2010

Я использую pdftk для заполнения формы PDF файлом XFDF. Однако для этого проекта я заранее не знаю, какие поля будут присутствовать, поэтому мне нужно проанализировать сам PDF, чтобы увидеть, какие поля необходимо заполнить, соответственно представить интерфейс для пользователя и затем сгенерировать файл XFDF из чтобы заполнить форму PDF.

Как я могу получить имена полей? Желательно решения для командной строки, .NET или PHP.

Ответы [ 6 ]

43 голосов
/ 16 сентября 2010

Легко! Вы уже используете pdftk

# pdftk input.pdf dump_data_fields

Он выведет имя поля, тип поля, некоторые его свойства (например, какие есть варианты для выпадающего списка или выравнивания текста) и даже текст всплывающей подсказки (который я считаю очень полезным)

Единственное, чего мне не хватает, это координаты поля ...

7 голосов
/ 22 сентября 2015

Это сработало для меня:

 pdftk 1.pdf dump_data_fields output test2.txt

Затем, когда файл зашифрован паролем, вы можете прочитать его

 pdftk 1.pdf input_pw YOUR_PASSWORD_GOES_HERE dump_data_fields output test2.txt

Это заняло у меня 2 часа, чтобы получить права, поэтому, надеюсь, я сэкономлю вам время :)

1 голос
/ 27 июня 2012

Очень поздний ответ от меня, хотя мое решение не PHP, но я надеюсь, что оно может пригодиться, если кто-то ищет решение для Ruby.

Сначала нужно использовать pdftk для извлечения имен всех полей, затем нам нужно очистить текст дампа, чтобы получить хороший читаемый хеш:

def extract_fields(filename)
  field_output = `pdftk #{filename} dump_data_fields 2>&1`
  @fields = field_output.split(/^---\n/).map do |field_text|
    if field_text =~ /^FieldName: (\w+)$/
      $1
    end
  end.compact.uniq
end

Во-вторых, теперь мы можем использовать любой синтаксический анализ XML для построения нашего XFDF:

# code borrowed from `nguyen` gem [https://github.com/joneslee85/nguyen]
# generate XFDF content
def to_xfdf(fields = {}, options = {})
  builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
    xml.xfdf('xmlns' => 'http://ns.adobe.com/xfdf/', 'xml:space' => 'preserve') {
      xml.f(:href => options[:file]) if options[:file]
      xml.ids(:original => options[:id], :modified => options[:id]) if options[:id]
      xml.fields {
        fields.each do |field, value|
          xml.field(:name => field) {
            if value.is_a? Array
              value.each { |item| xml.value(item.to_s) }
            else
              xml.value(value.to_s)
            end
          }
        end
      }
    }
  end
  builder.to_xml
end

# write fdf content to path
def save_to(path)
  (File.open(path, 'w') << to_xfdf).close
end

Альт, вот основная логика. Я настоятельно рекомендую вам попробовать nguyen (https://github.com/joneslee85/nguyen) gem), если вы ищете легковесную библиотеку в Ruby.

1 голос
/ 30 апреля 2010

Я использовал следующий код, используя ABCpdf из WebSupergoo, но я думаю, что большинство библиотек имеют сопоставимые классы:

protected void Button1_Click(object sender, EventArgs e)
    {
        Doc thedoc = new Doc();
        string saveFile = "~/docs/f1_filled.pdf";
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        thedoc.Read(Server.MapPath("~/docs/F1_2010.pdf"));
        foreach (Field fld in thedoc.Form.Fields)
        {
            if (!(fld.Page == null))
            {
                sb.AppendFormat("Field: {0}, Type: {1},page: {4},x: {2},y: {3}\n", fld.Name, fld.FieldType.ToString(), fld.Rect.Left, fld.Rect.Top, fld.Page.PageNumber);
            }
            else
            {
                sb.AppendFormat("Field: {0}, Type: {1},page: {4},x: {2},y: {3}\n", fld.Name, fld.FieldType.ToString(), fld.Rect.Left, fld.Rect.Top, "None");
            }
            if (fld.FieldType == FieldType.Text)
            {
                fld.Value = fld.Name;
            }

        }

        this.TextBox1.Text = sb.ToString();
        this.TextBox1.Visible = true;
        thedoc.Save(Server.MapPath(saveFile));
        Response.Redirect(saveFile);
    }

Это делает 2 вещи: 1) Заполняет текстовое поле списком всех полей формы, показывая их имя, тип поля, номер страницы и позицию на странице (кстати, слева внизу 0,0). 2) Заполняет все текстовые поля их именами полей в выходном файле - распечатайте выходной файл, и все ваши текстовые поля будут помечены.

0 голосов
/ 27 сентября 2016

C # / ITextSharp

    public static void TracePdfFields(string pdfFilePath)
    {
        PdfReader pdfReader = new PdfReader(pdfFilePath);
        MemoryStream pdfStream = new MemoryStream();
        PdfStamper pdfStamper = new PdfStamper(pdfReader, pdfStream, '\0', true);

        int i = 1;
        foreach (var f in pdfStamper.AcroFields.Fields)
        {
            pdfStamper.AcroFields.SetField(f.Key, string.Format("{0} : {1}", i, f.Key));
            i++;
            //DoTrace("Field = [{0}] | Value = [{1}]", f.Key, f.Value.ToString());
        }
        pdfStamper.FormFlattening = false;
        pdfStamper.Writer.CloseStream = false;
        pdfStamper.Close();

        FileStream fs = File.OpenWrite(string.Format(@"{0}/{1}-TracePdfFields_{2}.pdf", 
            ConfigManager.GetInstance().LogConfig.Dir, 
            new FileInfo(pdfFilePath).Name, 
            DateTime.Now.Ticks));

        fs.Write(pdfStream.ToArray(), 0, (int)pdfStream.Length);
        fs.Flush();
        fs.Close();
    }
0 голосов
/ 24 января 2010

Я могу заставить своего клиента экспортировать файл XFDF (который содержит имена полей), используя Acrobat вместе с PDF, что полностью устраняет эту проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...