简体   繁体   中英

How can I create a PDF form using PDFMARK and/or PERL cpan module PDF::API2?

Does anyone have any sample that demonstrates how one may create a simple PDF form (single text input box, or single radio button) and 'submit field_name/value pairs via HTTP post' to server when clicked, using either of three methods?

  1. By embedding Adobe's PDFMARK comments into a Postscript file, then convert the Postscript file to PDF via Adobe distiller or ghostscript? I read the PDFMARK documentation and it only briefly mentions one 'action' can be sent to 'form submit'. but the docs are sorely lacking in true detail of that implementation. Usually Adobe's docs are very great, but the author must have been pressed to finish that chapter before he actually finished it. Lacking in the details is that PDF forms may actually submit up to four different types of packets to a server, none of this is mentioned. As well, the actual syntax of the 'form submit' action is not even presented.
  2. By using PERL and the free PDF::API2 or 3 PDF manipulation library. The author has made available low level function calls that he believes allows enough possibility to actually achieve this but alas, has not actually used his library to do this specific task. Has anyone out there figured out how to do this with his library? I ask as I am primarily a programmer in Perl.
  3. Finally, if neither of above yield anything to me, does anyone know of ANY windows command line callable method to do this using free or relatively low cost software (less than $200). I would be willing to learn another language if this may be achieved using a different development environment.

Using pdfmark in a PostScript language program

First, I'll tackle part 1 of your question: creating such a PDF form file, by running a PostScript language program with pdfmark expressions through Adobe Acrobat Distiller or the like. See the sample program below.

The "PDFMARK documentation" which you read was the pdfmark Reference , I take it. My copy is dated November 2006. The code you need is almost all right there, in Examples 5.11 Define the AcroForm dictionary at the document Catalog and 5.12 Define the Widget annotations, which are also field dictionaries for this form , on pages 70-75. Read the code there carefully, copy it into a source file and distill it, modify to suit. That's what my sample is based on.

Be sure to read carefully Chapter 1 Introduction (p.9-16), which will help you read the pdfmark syntax in Examples 5.11 and 5.12. The section Named objects (p. 12-16) is important for understanding how the fonts and encodings in the examples are referenced.

But you also need to read the PDF language specification. Adobe's copy of the spec has been superseded by the ISO standard PDF 32000-1:2008 Document management — Portable document format — Part 1: PDF 1.7 Read Section 12.7 Interactive Forms (pp. 430-456), which will frequently refer you to Section 12.5 Annotations (pp. 381-414) for controls on the appearance of form fields.

The important thing to understand is that most the form fields will be defined by key-value pairs delivered in a PostScript language [ ... /ANN pdfmark expressions. The key-value pairs are specified in the PDF specification, not the pdfmark specification. But it's easy to edit the pdfmark expressions while reading the PDF specification.

The following program distills into a PDF file with form fields:

% Simple pdfmark form example
% by Jim DeLaHunt, jdlh.com, 3. March 2012
%
% This PostScript language code, when converted to PDF by 
% Adobe Acrobat Distiller or the like, creates a PDF file with form
% fields, and a Submit button which sends the values of the fields
% via an HTTP POST request.
%
% In reply to Stack Overflow question, "How can I create a PDF form 
% using PDFMARK and/or PERL cpan module PDF::API2?",
% http://stackoverflow.com/questions/9440930/
%

% Define stubs for interpreters without pdfmark support
% From pdfMark reference, Example 1.2, p.10
/pdfmark where {
    % pdfmark is built-in
    % define {code} ?pdfmark - : exec modal PDF code.
    pop globaldict /?pdfmark /exec load put
}{
    globaldict begin
        /?pdfmark /pop load def% pdfmark is absent: ignore code.
        /pdfmark /cleartomark load def
    end
} ifelse
%%EndProlog

% This code makes the example clearer. It isn't part of the AcroForm.
<</PageSize [300 300]>> setpagedevice  % smaller page (~ 10cm x 10cm)

clippath 0.9 setgray fill  % light grey background, to show widgets.
/Helvetica-Bold 12 selectfont 0 setgray  % for labels
/showlabel {   % (text) x y showlabel - 
    % shows (text) top-justified at x,y, moves down one line
    -12 add moveto   % x y -12 add moveto -
    gsave show grestore
    0 -3 rmoveto  % leading (space between lines)
} def
/showcomment {  % (text) showcomment - 
    % shows (text) top-justified at current point, moves down 1 line
    0 -10 rmoveto 
    gsave /Helvetica 10 selectfont show grestore
    0 -2 rmoveto  % leading (space between lines)
} def

(Simple pdfmark form example) 10 290 showlabel


% AcroForm dictionary setup. From pdfmark Reference, Example 5.11, p.70
%
% Read also PDF specification PDF32000:2008 
% "Document management — Portable document format — Part 1: PDF 1.7",
% Section 12.7 "Interactive Forms", p.430
% To understand the syntax: [/_objdef {foo} /type /dict /OBJ pdfmark
% read carefully pdfMark reference, "User-defined named objects", p.13.

% Define font objects for the widgets to use
[ /_objdef {ZaDb} /type /dict /OBJ pdfmark
[ {ZaDb} <<
    /Type /Font
    /Subtype /Type1
    /Name /ZaDb
    /BaseFont /ZapfDingbats
>> /PUT pdfmark
[ /_objdef {Helv} /type /dict /OBJ pdfmark
[ {Helv} <<
    /Type /Font
    /Subtype /Type1
    /Name /Helv
    /BaseFont /Helvetica
    % /Encoding {pdfDocEncoding} % for simplicity, use font's own encoding
    % pdfmark Reference, Example 5.11, p.70, provides an Encoding
    % array defining PDFDocEncoding
>> /PUT pdfmark

[ /_objdef {aform} /type /dict /OBJ pdfmark

% Define Fields array of Acroform dictionary. It will contain entries for
% each of the widgets defined below.
% NOTE: It is not necessary to explicitly assign the widget annotations
% to the Fields array; Acrobat does it automatically when the file is
% opened.  

[ /_objdef {afields} /type /array /OBJ pdfmark
[ {aform} <<
    /Fields {afields}
    /DR << /Font << /ZaDb {ZaDb} /Helv {Helv} >> >>
    /DA (/Helv 0 Tf 0 g)
    /NeedAppearances true
    % "/NeedAppearances true" tells reader 'to construct appearance
    % streams and appearance dictionaries for all widget annotations
    % in the document...' --PDF32000:2008 Table 218 p.431
>> /PUT pdfmark

% Put Acroform entry in catalog dictionary
[ {Catalog} << /AcroForm {aform} >> /PUT pdfmark


% Example 5.12 Define the Widget annotations
% pdfmark Reference pp. 72-75, with clarifications by Jim DeLaHunt
%
% These Widget annotations are also field dictionaries for this form.
% This is the collection of all individual widget annotations. 
% It is possible to have multiple instances of these sections, such as
% for defining a single widget on each instance.
%
% See PDF32000:2008 Section 12.5.6.19 "Widget Annotations", p.408
% especially tables 188 and 189.

(/Tx text field) 10 260 showlabel
(with Javascript) showcomment (validation) showcomment
[ /Subtype /Widget
    /Rect [100 223 245 260]
    /F 4
    /T (SL Text)
    /FT /Tx
    /DA (/Helv 14 Tf 0 0 1 rg)
    /V (5)
    /AA <<
        /K << 
            /S /JavaScript 
            /JS (AFNumber_Keystroke\(2, 0, 0, 0, "$", true\);)
        >>
        /F << 
            /S /JavaScript 
            /JS (AFNumber_Format\(2, 0, 0, 0, "$", true\);)
            % pdfmark Reference p.72 seems to omit closing ")" above. Oops.
        >>
    >>
/ANN pdfmark

(/Btn field) 10 208 showlabel
(Check Box) showcomment
[  /Subtype /Widget
    /Rect [100 172 136 208]
    /F 4
    /T (Check Box)
    /FT /Btn
    /DA (/ZaDb 0 Tf 0 g)
    /AS /Off
    /MK << /CA (4)>>
    /AP << /N << /Oui /null >> >>
/ANN pdfmark

(/Ch field) 10 160 showlabel
(List Box) showcomment
[   /Subtype /Widget
    /Rect [100 87 137 160]
    /F 4
    /T (List Box)
    /FT /Ch
    /DA (/Helv 10 Tf 1 0 0 rg)
    /Opt [(1)(2)(3)(4)(5)]
    /DV (3)
    /V (3)
    /MK <<
        /BG [1 1 1]   % Background: white
        /BC [0 0 0]   % Border colour: black
    >>
    % MK is 'An appearance characteristics dictionary (see Table 189)'
    % --PDF32000:2008 Table 188 p.408
    % Without an /MK entry, Acrobat Pro 8.0 complains of an error
    % when displaying this field, and some entries aren't displayed.

/ANN pdfmark

(/Btn button) 160 85 showlabel
(/S /SubmitForm action) showcomment
% Example of how the /MK dictionary is used.
[   /Subtype /Widget
    /Rect [ 130 10 270 50 ]
    /F 4
    /T (Submit)
    /FT /Btn
    /H /P
    /A << 
        /S /SubmitForm 
        /F (http://posttestserver.com/post.php) % Thanks, Henry!
        /Flags 16#6 % IncludeNoValueFields, ExportFormat
    >>
    /DA (/HeBo 18 Tf 0 0 1 rg)
    /Ff 65536
    /MK <<
        /BC [ 1 0 0 ]
        /BG [ 0.75 0.45 0.75 ]
        /CA (Submit)
        /AC (Submitted!)
    >>
    /BS <<
        /W 3
        /S /I
    >>
/ANN pdfmark

% When pressing the Submit button in Adobe Acrobat Professional 8.3.1,
% there is a pause, and then Acrobat displays a PDF file with the
% results of the HTTP POST operation. This is text like,
%   Successfully dumped 3 post variables. View it at
%   http://www.posttestserver.com/data/2012/03/04/01.29.271751566025 
%   Post body was 0 chars long.
%
% Browse to that URL, and you will see diagnostics with the following:
%   ....
%   Post Params:
%   key: 'Check_Box' value: 'Oui'
%   key: 'List_Box' value: '4'
%   key: 'SL_Text' value: '3.14'
%   Empty post body.

showpage  % make sure a page gets produced

Open the resulting PDF document in a PDF reader. Change the values in the forms. Note that the top text field limits you to a number with two decimal places, and it places a $ sign in front of the number. It does this with Javascript code. There is a checkbox, which sends the value Oui when checked.

When you click on the Submit button, the PDF reader takes the keys for each form field and the value of that field, and sends them to a URL via an HTTP POST call. The destination I used is Henry's HTTP Post Dumping Server . The server returns a text reply to the POST, giving a URL where you can see what the server received. Adobe Acrobat Professional turns this reply into a PDF file, which may take a few seconds. Visit that URL, and you can see the field_name/value pairs you seek.

Using PERL module PDF::API2

I'm not very experienced with Perl, and I've never used the PDF::API2 module . However, from a code inspection I suspect it will not be straightforward to generate PDF forms with PDF::API2.

The PDF::API2::Annot sub-module does look promising. But in order to use the method of the example program above, one must create PDF Annotations of /Subtype /Widget . It appears PDF::API2::Annot does not support this.

Looking through the source code of PDF::API2::Annot , one can see examples of how it handles other Annotation types. For example, the Link annotation type is created in part by code like:

$self->{Subtype}=PDFName('Link');

Were Widget annotations to be supported, one would expect to see statements like $self->{Subtype}=PDFName('Widget') . But there is no instance of the string Widget in this module (version 2.019). Hence, it will likely take an extension to this module to support Widget annotations.

Now Annotations are only PDF dictionaries with specific contents. It is probably possible to use PDF::API2::Basic::PDF::Dict to construct Widget annotations from basic parts. However, I'm guessing that this would be even more work than extending PDF::API2::Annot .

Take this question, and the bounty it attracted, as a sign: there will be much rejoicing if someone adds Widget annotation support to PDF::API2::Annot , and perhaps makes a PDF::API2::Form module!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM