PDF Form Submission Acrobat to REST API Server
What this solution is for
People who still want the client filled PDF Document.
Mostly because of the government regulation or some legacy work process.
But they are too painful with the PDF human key in mistake or tedious work of doing so.
Warning
This solution is possible in Adobe Acrobat only.
This will never work on subset of software that implement PDF e.g. Google Chrome, MS Edge and almost all online or offline PDF reader.
Prepare the form
You need to create the fillable PDF form like so from Acrobat Pro
On the right hand side go to “Prepare Form”.
Then fill in the editable field then button.
After adding functinoality you config what your button will do.
Don’t confuse by the bad UX. Pick drop down. Click Add.
The actions is ONLY what is in the actions box. You can add multiple actions like clearing the form afterward.
Common mistake
The popup ‘Unkown Format’ URL on Acrobat form submission
Credit to this forum
I spent sometime decrpyting their answer so what exactly we need is
Make the server response with the headers format that make Acrobat happy which are:
Content-Type: application/vnd.fdf
Content-disposition: inline
Note that this is mandatory to get rid of the error message
Popup the success message
When the form success, we have no clue on the submission status.
We have response something from the server and possibly popup the success message from the Acrobat screen.
This can be done by putting the Javascript inside the FDF response body. This must be set at your REST API server
Content-Type: application/vnd.fdf
Content-disposition: inline
Body: %FDF-1.2
1 0 obj
<<
/FDF
<<
/JavaScript
<<
/Doc 2 0 R
/After (confirmSend();)
>>
>>
>>
endobj
2 0 obj
[
(confirmSend) 3 0 R
]
endobj
3 0 obj
<<
>>
stream
function confirmSend()
{
app.alert({
cTitle : 'Submission Result',
cMsg : 'Your form name {{{first_name}}} client id {{{client_id}}} submission is success.',
nIcon : 3
});
}
endstream
endobj
trailer
<<
/Root 1 0 R
>>
%%EOF
Here we go. I think we have done all the must-have function.
See you next time.
Bonus: My Python AWS Lambda REST Server
This code accept Acrobat PDF submission and append it to the CSV file inside S3.
import json
import boto3
import csv
import urllib
BUCKET_NAME = 'my-demo'
OBJECT_NAME = 'sample/output.csv'
LAMBDA_LOCAL_TMP_FILE = '/tmp/test.csv'
FDF_RESPONSE_TEMPLATE = '''
%FDF-1.2
1 0 obj
<<
/FDF
<<
/JavaScript
<<
/Doc 2 0 R
/After (confirmSend();)
>>
>>
>>
endobj
2 0 obj
[
(confirmSend) 3 0 R
]
endobj
3 0 obj
<<
>>
stream
function confirmSend()
{
app.alert({
cTitle : 'Submission Result',
cMsg : 'Your form name {{{first_name}}} client id {{{client_id}}} submission is success.',
nIcon : 3
});
}
endstream
endobj
trailer
<<
/Root 1 0 R
>>
%%EOF
'''
def lambda_handler(event, context):
s3 = boto3.client('s3')
s3.download_file(BUCKET_NAME, OBJECT_NAME, LAMBDA_LOCAL_TMP_FILE)
body = urllib.parse.parse_qs(event['body'])
first_name = body['first_name'][0]
client_id = body['client_id'][0]
country = body['country'][0]
row = [first_name, client_id, country]
with open(LAMBDA_LOCAL_TMP_FILE, 'a') as f:
writer = csv.writer(f)
writer.writerow(row)
s3.upload_file(LAMBDA_LOCAL_TMP_FILE, BUCKET_NAME, OBJECT_NAME)
return {
'statusCode': 200,
'body': FDF_RESPONSE_TEMPLATE.replace('{{{first_name}}}', first_name).replace('{{{client_id}}}', client_id),
'headers': {
'Content-Type': 'application/vnd.fdf',
'Content-disposition' : 'inline'
}
}