Acrobat User Community

Importing and exporting PDF file attachments with Acrobat JavaScript and Acrobat 9

By Thom ParkerApril 30, 2009

A PDF file has the ability to encapsulate other file types, such as a ".zip" file. The user can quite literally drag and drop files in and out of a PDF. This ability to attach files is the basis for several other features in Acrobat, most notably "Packages" in Acrobat 8, "Portfolios" in Acrobat 9 and "Data Collection" files. File attachments are a very useful and important PDF feature, and Acrobat JavaScript provides several functions and properties for manipulating the file attachments. This article will explore the functions for importing and exporting file attachments into and out of a PDF.

Attachments in PDF: a JavaScript perspective

For the user, file attachments are handled in the File Attachments Panel, accessed from the View > Navigation Panels > Attachments menu item. All operations that can be performed in this panel and more are available using JavaScript, although with some caveats.

In the nomenclature for Acrobat JavaScript, a file attachment is called a "Data" object. So, in the Acrobat JavaScript Reference all the Objects, Functions, and Properties related to file attachments have the words "Data" or "DataObject" in them. For example, all file attachments are listed in the doc.dataObjects property. In this article, we'll be looking at the doc.importDataObject() and doc.exportDataObject() functions.

File attachments present a security dilemma for Acrobat JavaScript. While they are very useful, there is the potential for them to be used in an unfriendly way. For example, you wouldn't want code in a PDF importing and exporting file attachments without your knowledge, especially if those file attachments were executable files. But if you are writing a workflow-automation script, then you definitely want these operations to be silent. As a result of these two situations, the file attachment functions have a split personality. They act one way when called from a privileged context, and a different way when called from a document script.

Here are the rules for handling file attachments with JavaScript:

  1. By default, certain file types (".exe", ".zip", ".js", etc) can be imported, but not exported or opened from a PDF. On Windows, the exact file types are listed in the Registry at: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Adobe\Adobe Acrobat\8.0\FeatureLockDown\cDefaultLaunchAttachmentPerms
  2. When used from a non-privileged context, such as a document script, the import and export functions always display a file open or file save dialog that allows the user to decide "if" and "where" the files will be imported or exported to/from.
  3. If used from a privileged context, the import file path can be specified in a script so the import function can be run silently.
  4. In Adobe Reader, importing a file attachment changes the PDF so it requires Reader "Embedding" Rights. This is not one of the rights that can be set with Acrobat Professional. The only way to apply "Embedding" Rights to a PDF is through the LiveCycle ES Rights Enabling Server.

Given these rules, you can see that the import and export file attachment functions are much more useful for writing automation scripts than they are for writing document scripts. However, there are still some very useful things we can do.

Importing file attachments

The doc.importDataObject() function cannot be used from Adobe Reader without special Rights Enabling that is not available to most users. So unfortunately, it is typically not suitable for a script inside a PDF. The primary use of this function is in automation scripting. In fact, there is one very important reason for using it by itself to import file attachments-- to create Named Attachments. Scripts need the name of the file attachment in order to work with them.

When a file is attached to a PDF using the Acrobat user interface, such as dragging and dropping it into the File Attachments navigation panel, Acrobat gives the file attachment a default name. This default name is always a variation on "Unknown Object." While the default is usable, it is neither descriptive nor easy to work with. File attachment names cannot be changed after the file is imported. So if a script on the document will be using the file attachments, it's a good idea to use the doc.importDataObject() function to import the files with a specific name. This function can be run from the console window. The following code displays a File Open dialog for the user to select the file to attach, and then gives the file attachment the name "MyFile."

this.importDataObject("MyFile");

PDF file attachments must have unique names. So if this function is called a second time with the same name, then the first file attachment will be overwritten.

This code can be run from script in a document or in an automation script run from a toolbar button. I've already created such an automation tool and it's available as a free download at www.pdfscripting.com. Click on the Free Automation tools link and scroll to the bottom of the page to the "Import Named File Attachment" tool.

In a workflow automation script, the files will most likely need to be imported silently. To run the doc.importDataObject()function silently, the file path must be specified and it must be run from a privileged context, i.e., it cannot be run from a script in a document. Here's an example trusted function that shows how this is done:

for(var i=0;i<this.numFields;i++)
var importMyAttachment = app.trustedFunction( function(cAttName, cFilePath){
	app.beginPriv();
	var rtn = this.importDataObject(cAttName,cPath);
	app.endPriv();
});
// Call function, can be called from any context importMyAttachment("Mine","/c/temp/myfile.pdf");

File-attachment description:

All file attachments in a PDF have an associated "Description," which is displayed in the File Attachments panel in Acrobat. The "Description" is set after the file has been successfully imported. Here's some code that shows how to set the description property of a file attachment named "MyFile."

var oAttach = this.getDataObject("MyFile");
if(oAttach) oAttach.description = "This is my File";

The text "This is my File" will now appear in the description field for this file attachment in the File Attachments navigation panel in both Acrobat and Adobe Reader. If no description is provided, the import name will appear in this field.

Exporting file attachments

As stated above, using a script to export a file from a PDF is considered a major security risk. However, PDF file attachments are not the problem. Since a PDF can attach literally any file type, it is other file types of unknown characteristics that create a security issue. Because of this, the doc.exportDataObject() function will always display a file open dialog in order to keep the user involved in the file-export process. This is a big pain for writing automation scripts. But fortunately, there is another way to export attached PDF files, and there is another more important use for the doc.exportDataObject() function.

First, let's take a look at this other use for the doc.exportDataObject() function. This function includes an input parameter for launching or opening an attached file in the default program used to view that file type. For example, on Windows a ".txt" file would be opened in NotePad and a ".doc" file would be opened in Word.

As an example, let's assume that the doc.importDataObject() function was used to import a Word file and give it a file attachment name "MyDoc." Here's the code that will open this file attachment in Word:

this.exportDataObject({cName:"MyDoc", nLaunch:2});

The "cName" parameter is a required input and specifies the specific file attachment that will be exported. Notice there is no path parameter. There is in fact a "cPath" input to this function, but it is no longer valid. If you try to use a path in this function, it will fail and throw an exception. It doesn't matter what context the function is called from because the "cPath" parameter was removed from all usage.

An nLaunch value of "2" directs Acrobat to save the file attachment to a temporary file and then ask the operating system to open it (Acrobat doesn't know anything about which programs open which file types, but the OS does). Other possible values are 0 and 1. A value of "0" causes the file to be saved, and a value of "1" causes the file to be opened after it is saved. Both of these options will cause the File Open Dialog to be displayed. All the variations for the code shown above will work from any context. This code will work in an automation or a PDF script, and it will work when a PDF is opened in Reader, i.e., there are no security restrictions. However, the first time this code is run, a popup will be displayed asking users if they are sure they want to allow the attachment to be exported. There's no getting around this popup, but at least it only happens once.

Here's a sample PDF that shows how this export code and the import code presented earlier are used, ImExportAttachSample.pdf. Scroll down to the bottom of the page to find the download file.

An alternate method for exporting an attachment that is a PDF file

The "exportDataObject()" function can't export any file silently, but if that file attachment is a PDF, there is an alternate method. A PDF file attachment can be opened by Acrobat and saved using the standard "doc.saveAs()" function. This strategy can only be used by an automation script.

Let me be clear about the situation. Silently exporting a file from a script inside a PDF can never be done. And for an automation script, we can only export a PDF file attachment silently. All other file types require user interaction no matter the context.

Now lets get on with the automation script for exporting a PDF file. First, because the "doc.saveAs()" function is privileged, the script has to be placed in a trusted function. Here's the code:

var exportMyPDFAttachment = app.trustedFunction( function(cAttName, cFilePath){
	app.beginPriv();
	var oDoc = this.openDataObject(cAttName);
	oDoc.saveAs(cPath); oDoc.closeDoc();
	app.endPriv();
});
// Call function for a file attachment named “Mine” exportMyPDFAttachment("Mine","/c/temp/myfile.pdf");

Notice that the name of the file is included in the save path. This is done to simplify the example, but the file name could have been extracted from the "path" property of the data object. To use this function in Adobe Reader, the file must also be enabled with "Save" rights.

That's it for importing and exporting file attachments using JavaScript, but there is much more that can be done with file attachments, or as they are called in JavaScript, Data Objects. For more information on these and related functions, see both The Acrobat JavaScript Reference and The Acrobat JavaScript Guide.

https://www.adobe.com/devnet/acrobat.html