As we transition to the new Hyland Community, some post links may be temporarily disrupted as we finalize redirects. We apologize for the inconvenience and are working to resolve this as quickly as possible. Details.
It appears the Acrobat is capable of running JavaScript http://partners.adobe.com/public/developer/en/acrobat/sdk/AcroJSGuide.pdf so it got me thinking that perhaps Alfresco Webscripts could read the PDF Forms.
function writeToProperty() { var fld = this.getField("dswf_clientName"); this.info.kcms_clientName = fld.value; } writeToProperty(); // call my function
function writeToProperty() { var fld = this.getField("sourceFieldName"); this.info.targetPropertyName = fld.value; } writeToProperty(); // call my function
try { // New - Use a temp file so it can be parsed twice tstream = TikaInputStream.get(stream, tmp); tsFile = tstream.getFile(); // PDFBox can process entirely in memory, or can use a temp file // for unpacked / processed resources // Decide which to do based on if we're reading from a file or not already if (tstream != null && tstream.hasFile()) { // File based, take that as a cue to use a temporary file scratchFile = new RandomAccessFile(tmp.createTemporaryFile(), "rw"); pdfDocument = PDDocument.load(tsFile, scratchFile); } else { // Go for the normal, stream based in-memory parsing pdfDocument = PDDocument.load(tsFile); } …snip code to cope with encrypted files… metadata.set(Metadata.CONTENT_TYPE, "application/pdf"); extractMetadata(pdfDocument, metadata); // New - Now parse again but non-sequentially to retrieve any form field data pdfFormDoc = PDDocument.loadNonSeq(tsFile, scratchFile); extractFormFieldData(pdfFormDoc, metadata); PDF2XHTML.process(pdfDocument, handler, metadata, extractAnnotationText, enableAutoSpace, suppressDuplicateOverlappingText, sortByPosition);
private void extractFormFieldData(PDDocument document, Metadata metadata) throws TikaException, IOException { PDDocumentCatalog docCatalog = document.getDocumentCatalog(); PDAcroForm acroForm = docCatalog.getAcroForm(); if (acroForm != null) { List fldList = acroForm.getFields(); Iterator fIter = fldList.iterator(); while(fIter.hasNext()){ PDField field = (PDField)fIter.next(); addMetadata(metadata, field.getFullyQualifiedName(), field.getValue()); if (logger.isDebugEnabled()) { String logMsg = "extracting: " + field.getFullyQualifiedName(); logMsg += " value: " + field.getValue(); logger.debug(logMsg); } } } }
public void parse( InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException { PDDocument pdfDocument = null; PDDocument pdfFormDoc = null; TikaInputStream tstream = null; File tsFile = null; TemporaryResources tmp = new TemporaryResources(); RandomAccess scratchFile = null; try { // SMD - Use a temp file so it can be parsed twice tstream = TikaInputStream.get(stream, tmp); tsFile = tstream.getFile(); // PDFBox can process entirely in memory, or can use a temp file // for unpacked / processed resources // Decide which to do based on if we're reading from a file or not already if (tstream != null && tstream.hasFile()) { // File based, take that as a cue to use a temporary file scratchFile = new RandomAccessFile(tmp.createTemporaryFile(), "rw"); // pdfDocument = PDDocument.load(new CloseShieldInputStream(stream), scratchFile, true); pdfDocument = PDDocument.load(tsFile, scratchFile); } else { // Go for the normal, stream based in-memory parsing // pdfDocument = PDDocument.load(new CloseShieldInputStream(stream), true); pdfDocument = PDDocument.load(tsFile); } if (pdfDocument.isEncrypted()) { String password = null; // Did they supply a new style Password Provider? PasswordProvider passwordProvider = context.get(PasswordProvider.class); if (passwordProvider != null) { password = passwordProvider.getPassword(metadata); } // Fall back on the old style metadata if set if (password == null && metadata.get(PASSWORD) != null) { password = metadata.get(PASSWORD); } // If no password is given, use an empty string as the default if (password == null) { password = ""; } try { pdfDocument.decrypt(password); } catch (Exception e) { // Ignore } } metadata.set(Metadata.CONTENT_TYPE, "application/pdf"); extractMetadata(pdfDocument, metadata); // SMD - Now parse non-sequentially to retrieve any form field data pdfFormDoc = PDDocument.loadNonSeq(tsFile, scratchFile); extractFormFieldData(pdfFormDoc, metadata); PDF2XHTML.process(pdfDocument, handler, metadata, extractAnnotationText, enableAutoSpace, suppressDuplicateOverlappingText, sortByPosition); } finally { if (pdfDocument != null) { pdfDocument.close(); pdfFormDoc.close(); } tmp.dispose(); } }
/** * Steve Deal - Added to parse PDF Form fields * * @param document * @param metadata * @throws TikaException */ private void extractFormFieldData(PDDocument document, Metadata metadata) throws TikaException, IOException { PDDocumentCatalog docCatalog = document.getDocumentCatalog(); PDAcroForm acroForm = docCatalog.getAcroForm(); if (acroForm != null) { List fldList = acroForm.getFields(); Iterator fIter = fldList.iterator(); while(fIter.hasNext()){ PDField field = (PDField)fIter.next(); addMetadata(metadata, field.getFullyQualifiedName(), field.getValue()); if (logger.isDebugEnabled()) { String logMsg = "extracting: " + field.getFullyQualifiedName(); logMsg += " value: " + field.getValue(); logger.debug(logMsg); } } } }
The only solution we have found is to rename the OOTB jar files and drop the modified jar files into the tomcat/webapps/alfresco/WEB-INF/lib.
INFO: Adding 'file:/opt/alfresco-4.0.d/alf_data/solr/lib/tika-parsers-1.1-20111128.jar' to classloader 07/08/2012 8:18:22 AM org.apache.solr.core.SolrResourceLoader replaceClassLoader
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'> <beans> <bean id="extracter.PDFBox" class="org.alfresco.repo.content.metadata.PdfBoxMetadataExtracter" parent="baseMetadataExtracter" > <property name="inheritDefaultMapping"> <value>true</value> </property> <property name="mappingProperties"> <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="location"> <value>classpath:alfresco/extension/custom-pdfbox-extractor-mappings.properties</value> </property> </bean> </property> </bean> </beans>
# Namespace Definitions namespace.prefix.cm=http://www.alfresco.org/model/content/1.0 namespace.prefix.my=my.companyName.root #Mapping Definitions testData=my:testData
<aspect name="my:testAspect"> <title>Test Aspect</title> <properties> <property name="my:testData"> <type>d:text</type> </property> </properties> </aspect>
For instance, say I have a test pdf form, created in Livecycle, with a field in it named "testData". If I also had defined in our content model an aspect: "my:testAspect" with a property "my:testData", would extracting common metadata on the pdf cause it to gain the my:testAspect aspect with the my:testData property set to whatever was entered in the form field? (without further modification)
<!– This adds in the extra mapping for the Open Document extractor –> <bean id="extracter.PDFBox" class="org.alfresco.repo.content.metadata.PdfBoxMetadataExtracter" parent="baseMetadataExtracter"> <property name="inheritDefaultMapping"> <value>true</value> </property> <property name="mappingProperties"> <props> <!– Metadata extraction –> <prop key="namespace.prefix.cm">http://www.alfresco.org/model/content/1.0</prop> <prop key="namespace.prefix.myns">http://www.acme.com/model/content/1.0</prop> <!– My Namespace Project Model –> <prop key="myns_projectName">myns:projectName</prop> <prop key="myns_organizationName">myns:organizationName</prop> <prop key="myns_organizationAddress">myns:organizationAddress</prop> </props> </property> </bean>
So does that work for you with properties entered only in the form fields (which is to say, does it work without the javascript from your other post setting custom properties from the form fields)?The only way I am able to get the test data out of the form (config as per my previous post) appears to be by setting a custom property. If I use liveCycle to add a custom property called testData, whatever I put in for the value of that property is used as metadata by Alfresco. So that, at least, works. However I do not get anything from form fields named testData. I tried to implement the javascript from your other post, I'm not sure if we use a different version or what, but as far as I can tell, the this.info object (from the scope of a field) doesn't exist. I tried form.info and xfa.info and a few others but to no avail.
WARN [content.metadata.AbstractMappingMetadataExtracter] [http-8443-6] Metadata extraction failed (turn on DEBUG for full error): Extracter: org.alfresco.repo.content.metadata.PdfBoxMetadataExtracter@ae747d3 Content: ContentAccessor[ contentUrl=store://2012/8/16/15/6/51db06bc-26e2-4871-a613-5e25e823ffac.bin, mimetype=application/pdf, size=50453, encoding=UTF-8, locale=en_US] Failure: Can't get signature as String, use getSignature() instead.null
while(fIter.hasNext()){ PDField field = (PDField)fIter.next(); String checkFieldType = field.getFieldType(); if (checkFieldType != "Sig") { addMetadata(metadata, field.getFullyQualifiedName(), field.getValue()); } }