How to work with associated files
Contents
System requirements
Platform: Windows, Mac, Linux
Programming Language: C, C++, C#, Java, Python, Objective-C
License Key requirement: standard license key
SDK Version: Foxit PDF SDK 6.0 or later
What is the “AF” attributes of PDF?
AF attributes are provided from the PDF 2.0 standard. AF Attributes (Attachment File Attributes) are metadata in PDF documents that allow additional files to be attached to PDF documents, such as Word documents, Excel tables, images, audio and video files, and more.
These additional files can be in other formats, not just PDFs.
Through the attachment function, PDF documents can be processed more intelligently. Specifically, it can realize the following functions:
1. Attach other files to the PDF file: Through the AF attribute, users can attach other files to the PDF document so that related files can be put together for easy management and viewing.
2. Extend the functions of PDF documents: Through the attachment function, other files can be packaged together with PDF documents to achieve some functions that cannot be realized by PDF documents themselves, such as embedding audio and video files, adding animation effects, providing interactive tables, etc.
3. Improve work efficiency: By attaching other files to PDF files, you can conveniently gather all related files in one place without switching applications frequently, which improves work efficiency.
4. Improve security: PDF files can be encrypted through the attachment function, and only authorized users can access the files in the attachment, ensuring the security of the files.
How to use associated files via the “AF” attributes
First, you need to understand the relationship between a PDF document and the associated file as follows:
● RelationshipSource: The relationship is “Source” which means the file specification is the original source material for the associated content.
● RelationshipData: The relationship is “Data” which means the file specification represents information used to derive a visual presentation – such as for a table or a graph.
● RelationshipAlternative: The relationship is “Alternative” which means the file specification is an alternative representation of content, for example audio.
● RelationshipSupplement: The relationship is “Supplement” which means the file specification represents a supplemental representation of the original source or data that may be more easily consumable.
● RelationshipEncryptedPayload: The relationship is “Encrypted payload” which means the file specification is an encrypted payload document that should be displayed to the user if the PDF processor has the cryptographic filter needed to decrypt the document.
● RelationshipFormData: The relationship is “Form data” which means the file specification is the data associated with the “AcroForm” dictionary in the PDF file.
● RelationshipSchema: The relationship is “Schema” which means the file specification is a schema definition for the associated object.
First, define a FileSpec object (a PDF file can refer to the contents of another file by using a file specification), and then the source document can be defined by the AF attribute type as follows:
How to intelligently locate the corresponding source document through the AF dictionary item of the object in the PDF page? as follows:
The file associated with the dictionary can be obtained through the GetAssociatedFile method.
Of course, these dictionary items can be various PDF dictionary objects, such as annot, form, graphicsObject, catalog dictionary, etc.
When the associated file is obtained through the AF attribute, you can use the ExportToFile method to export to the local, as follows:
Generate effect display:
Not only can the source file be obtained through the dictionary, but also the FileSpec Associate files with objects in PDF documents can be defined as follows:
Define source files and set properties:
Associate an object in a document with a FileSpec:
Embed the whole content of a PDF stream object or a PDF reference object that refers to a PDF stream object when the current file specification object is used as an associated file but only supported in PDF 2.0, as follows:
In short, according to the actual situation, select different AF attribute types and AF attribute values to determine the source file and generate PDF data to the source file.
Code display of working with associated files in various languages:
C++
#include "../../../include/common/fs_common.h"
#include "../../../include/pdf/fs_filespec.h"
#include "../../../include/pdf/fs_pdfassociatefiles.h"
#include "../../../include/pdf/fs_pdfdoc.h"
#include "../../../include/pdf/fs_pdfpage.h"
AssociatedFiles associated_files(doc);
PDFDictionary* doc_catalog_dict = doc.GetCatalog();
int count = associated_files.GetAssociatedFilesCount(doc_catalog_dict);
printf("The catalog dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
FileSpec filespec = associated_files.GetAssociatedFile(doc_catalog_dict, 0);
printf("The file name is \"%s\".\n\n", (const char*)String::FromUnicode(filespec.GetFileName()));
filespec.ExportToFile(output_directory + L"af_1.txt");
PDFPage page = doc.GetPage(0);
PDFDictionary* page_dict = page.GetDict();
count = associated_files.GetAssociatedFilesCount(page_dict);
printf("The page dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
filespec = associated_files.GetAssociatedFile(page_dict, 0);
printf("The file name is \"%s\".\n\n", (const char*)String::FromUnicode(filespec.GetFileName()));
filespec.ExportToFile(output_directory + L"af_2.txt");
Annot annot = page.GetAnnot(0);
PDFDictionary* annot_dict = annot.GetDict();
count = associated_files.GetAssociatedFilesCount(annot_dict);
printf("The annot dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
filespec = associated_files.GetAssociatedFile(annot_dict, 0);
printf("The file name is \"%s\".\n\n", (const char*)String::FromUnicode(filespec.GetFileName()));
filespec.ExportToFile(output_directory + L"af_4.txt");
FileSpec filespec_txt(doc);
filespec_txt.SetAssociteFileRelationship(AssociatedFiles::e_RelationshipSource);
filespec_txt.SetFileName(L"1.txt");
DateTime dateTime(2017, 9, 15, 17, 20, 20, 0, 8, 0);
filespec_txt.SetDescription("text");
filespec_txt.Embed(input_path + L"1.txt");
filespec_txt.SetCreationDateTime(dateTime);
filespec_txt.SetModifiedDateTime(dateTime);
filespec_txt.SetSubtype();
//Associate 1.txt with catalog dictionary.
{
PDFObject* catalog_dict = doc.GetCatalog();
associated_files.AssociateFile(catalog_dict, filespec_txt);
printf("Associate a text file with catalog dictionary.\n");
FileSpec filespec_catalog = associated_files.GetAssociatedFile(catalog_dict, 0);
filespec_catalog.ExportToFile(output_directory + L"catalog.txt");
}
JAVA
import com.foxit.sdk.pdf.graphics.FormXObject;
import com.foxit.sdk.pdf.graphics.GraphicsObject;
import com.foxit.sdk.pdf.graphics.ImageObject;
import com.foxit.sdk.pdf.graphics.MarkedContent;
import com.foxit.sdk.pdf.objects.PDFDictionary;
import com.foxit.sdk.pdf.objects.PDFObject;
AssociatedFiles associated_files = new AssociatedFiles(doc);
PDFDictionary doc_catalog_dict = doc.getCatalog();
int count = associated_files.getAssociatedFilesCount(doc_catalog_dict);
System.out.println("The catalog dictionary of \"AF_Catalog_Page_Annot.pdf\" has" + count + " associated files.");
FileSpec filespec = associated_files.getAssociatedFile(doc_catalog_dict, 0);
System.out.println("The file name is \"" + filespec.getFileName() + "\".");
filespec.exportToFile(output_path + "af_1.txt");
PDFPage page = doc.getPage(0);
PDFDictionary page_dict = page.getDict();
count = associated_files.getAssociatedFilesCount(page_dict);
System.out.println("The page dictionary of \"AF_Catalog_Page_Annot.pdf\" has " + count + " associated files.");
filespec = associated_files.getAssociatedFile(page_dict, 0);
System.out.println("The file name is \"" + filespec.getFileName() + "\".");
filespec.exportToFile(output_path + "af_2.txt");
Annot annot = page.getAnnot(0);
PDFDictionary annot_dict = annot.getDict();
count = associated_files.getAssociatedFilesCount(annot_dict);
System.out.println("The annot dictionary of \"AF_Catalog_Page_Annot.pdf\" has " + count + " associated files.");
filespec = associated_files.getAssociatedFile(annot_dict, 0);
System.out.println("The file name is \"" + filespec.getFileName() + "\".");
filespec.exportToFile(output_path + "af_4.txt");
// Create filespec with 1.txt
FileSpec filespec_txt = new FileSpec(doc);
filespec_txt.setAssociteFileRelationship(e_RelationshipSource);
filespec_txt.setFileName("1.txt");
DateTime dateTime = new DateTime(2017, 9, 15, 17, 20, 20, 0, (short) 8, 0);
filespec_txt.setDescription("text");
filespec_txt.embed(input_path + "1.txt");
filespec_txt.setCreationDateTime(dateTime);
filespec_txt.setModifiedDateTime(dateTime);
filespec_txt.setSubtype("application/octet-stream");
// Associate 1.txt with catalog dictionary.
{
PDFObject catalog_dict = doc.getCatalog();
associated_files.associateFile(catalog_dict, filespec_txt);
System.out.println(String.format("Associate a text file with catalog dictionary."));
FileSpec filespec_catalog = associated_files.getAssociatedFile(catalog_dict, 0);
filespec_catalog.exportToFile(output_path + "catalog.txt");
}
Python
associated_files = AssociatedFiles(doc)
doc_catalog_dict = doc.GetCatalog()
count = associated_files.GetAssociatedFilesCount(doc_catalog_dict)
print('The catalog dictionary of "AF_Catalog_Page_Annot.pdf" has {}associated files.'
.format(count))
filespec = associated_files.GetAssociatedFile(doc_catalog_dict, 0)
print('The file name is "{}"'.format(filespec.GetFileName()))
filespec.ExportToFile(output_directory + "af_1.txt")
page = doc.GetPage(0)
page_dict = page.GetDict()
count = associated_files.GetAssociatedFilesCount(page_dict)
print('The page dictionary of "AF_Catalog_Page_Annot.pdf" has {} associated files.'
.format(count))
filespec = associated_files.GetAssociatedFile(page_dict, 0)
print('The file name is "{}".'.format(filespec.GetFileName()))
filespec.ExportToFile(output_directory + "af_2.txt")
annot = page.GetAnnot(0)
annot_dict = annot.GetDict()
count = associated_files.GetAssociatedFilesCount(annot_dict)
print('The annot dictionary of "AF_Catalog_Page_Annot.pdf" has {} associated files.'
.format(count))
filespec = associated_files.GetAssociatedFile(annot_dict, 0)
print('The file name is "{}"'.format(filespec.GetFileName()))
filespec.ExportToFile(output_directory + "af_4.txt")
C#
using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.graphics;
using foxit.pdf.objects;
using foxit.pdf.annots;
using(PDFDictionary doc_catalog_dict = doc.GetCatalog()) {
int count = associated_files.GetAssociatedFilesCount(doc_catalog_dict);
Console.WriteLine("The catalog dictionary of \"AF_Catalog_Page_Annot.pdf\" has" + count + " associated files.");
using(FileSpec filespec = associated_files.GetAssociatedFile(doc_catalog_dict, 0)) {
Console.WriteLine("The file name is \"" + filespec.GetFileName() + "\".");
filespec.ExportToFile(output_path + "af_1.txt");
}
using(PDFPage page = doc.GetPage(0))
using(PDFDictionary page_dict = page.GetDict()) {
count = associated_files.GetAssociatedFilesCount(page_dict);
Console.WriteLine("The page dictionary of \"AF_Catalog_Page_Annot.pdf\" has " + count + " associated files.");
using(FileSpec filespec = associated_files.GetAssociatedFile(page_dict, 0)) {
Console.WriteLine("The file name is \"" + filespec.GetFileName() + "\".");
filespec.ExportToFile(output_path + "af_2.txt");
}
using(Annot annot = page.GetAnnot(0))
using(PDFDictionary annot_dict = annot.GetDict()) {
count = associated_files.GetAssociatedFilesCount(annot_dict);
Console.WriteLine("The annot dictionary of \"AF_Catalog_Page_Annot.pdf\" has " + count + " associated files.");
using(FileSpec filespec = associated_files.GetAssociatedFile(annot_dict, 0)) {
Console.WriteLine("The file name is \"" + filespec.GetFileName() + "\".");
filespec.ExportToFile(output_path + "af_4.txt");
}
}
}
using (foxit.common.DateTime dateTime = new foxit.common.DateTime(2017, 9, 15, 17, 20, 20, 0, 8, 0))
{
filespec_txt.SetDescription("text");
filespec_txt.Embed(input_path + "1.txt");
filespec_txt.SetCreationDateTime(dateTime);
filespec_txt.SetModifiedDateTime(dateTime);
filespec_txt.SetSubtype("application/octet-stream");
//Associate 1.txt with catalog dictionary.
{
PDFObject catalog_dict = doc.GetCatalog();
associated_files.AssociateFile(catalog_dict, filespec_txt);
Console.WriteLine("Associate a text file with catalog dictionary.");
using (FileSpec filespec_catalog = associated_files.GetAssociatedFile(catalog_dict, 0))
{
filespec_catalog.ExportToFile(output_path + "catalog.txt");
}
}
C
#include <time.h>
#include<direct.h>
#include <stdio.h>
#include "../../../include/fs_basictypes_c.h"
#include "../../../include/fs_common_c.h"
#include "../../../include/fs_filespec_c.h"
#include "../../../include/fs_pdfassociatefiles_c.h"
#include "../../../include/fs_pdfdoc_c.h"
#include "../../../include/fs_pdfpage_c.h"
#include "../../../include/fs_pdfobject_c.h"
static const wchar_t* output_path = L"../output_files/";
static const wchar_t* input_path = L"../input_files/";
int main(int argc, char *argv[]) {
int err_ret = 0;
FSErrorCode error_code = e_FSErrSuccess;
wchar_t input_file[MAX_FILE_PATH] = { 0 };
wchar_t output_directory[MAX_FILE_PATH] = { 0 };
error_code = FSDK_Library_Initialize(sn, key);
if (error_code != e_FSErrSuccess) {
printf("Library Initialize Error: %d\n", error_code);
return 1;
}
swprintf_s(input_file, MAX_FILE_PATH, L"%lsAF_Catalog_Page_Annot.pdf", input_path);
swprintf_s(output_directory, MAX_FILE_PATH, L"%lsassociated_files/", output_path);
_wmkdir(output_directory);
// Get information about associated files from PDF document.
{
FS_PDFDOC_HANDLE doc = NULL;
FS_ASSOCIATEDFILES_HANDLE associated_files = NULL;
FS_PDFDICTIONARY_HANDLE doc_catalog_dict = NULL;
int count = 0;
FS_FILESPEC_HANDLE filespec = NULL;
FS_WSTR str;
wchar_t output_file[MAX_FILE_PATH] = { 0 };
FS_BOOL return_result = FALSE;
FS_PDFPAGE_HANDLE page = NULL;
FS_PDFDICTIONARY_HANDLE page_dict = NULL;
FS_ANNOT_HANDLE annot = NULL;
FS_PDFDICTIONARY_HANDLE annot_dict = NULL;
error_code = FSDK_PDFDoc_Create0(input_file, &doc);
if (error_code != e_FSErrSuccess) {
printf("Open file failed: %d\n", error_code);
return 1;
}
error_code = FSDK_PDFDoc_Load(doc, NULL);
if (error_code != e_FSErrSuccess) {
printf("Load document failed: %d\n", error_code);
FSDK_PDFDoc_Release(doc);
return 1;
}
error_code = FSDK_AssociatedFiles_Create(doc, &associated_files);
error_code = FSDK_PDFDoc_GetCatalog(doc, &doc_catalog_dict);
if (error_code != e_FSErrSuccess) {
FSDK_PDFDoc_Release(doc);
return 1;
}
error_code = FSDK_AssociatedFiles_GetAssociatedFilesCount(associated_files, doc_catalog_dict, &count);
printf("The catalog dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
error_code = FSDK_AssociatedFiles_GetAssociatedFile(associated_files, doc_catalog_dict, 0, &filespec);
FSDK_WStr_Init(&str);
error_code = FSDK_FileSpec_GetFileName(filespec, &str);
wprintf(L"The file name is \"%ls\".\n\n", str.str);
swprintf_s(output_file, MAX_FILE_PATH, L"%lsaf_1.txt", output_directory);
FSDK_FileSpec_ExportToFile(filespec, output_file, &return_result);
error_code = FSDK_PDFDoc_GetPage(doc, 0, &page);
if (error_code != e_FSErrSuccess) return 1;
error_code = FSDK_PDFPage_GetDict(page, &page_dict);
if (error_code != e_FSErrSuccess) {
FSDK_PDFPage_Release(page);
return 1;
}
FSDK_AssociatedFiles_GetAssociatedFilesCount(associated_files, page_dict, &count);
printf("The page dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
FSDK_AssociatedFiles_GetAssociatedFile(associated_files, page_dict, 0, &filespec);
FSDK_FileSpec_GetFileName(filespec, &str);
wprintf(L"The file name is \"%ls\".\n\n", str.str);
swprintf_s(output_file, MAX_FILE_PATH, L"%lsaf_2.txt", output_directory);
FSDK_FileSpec_ExportToFile(filespec, output_file, &return_result);
FSDK_PDFPage_GetAnnot(page, 0, &annot);
FSDK_Annot_GetDict(annot, &annot_dict);
FSDK_AssociatedFiles_GetAssociatedFilesCount(associated_files, annot_dict, &count);
printf("The annot dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
FSDK_AssociatedFiles_GetAssociatedFile(associated_files, annot_dict, 0, &filespec);
FSDK_FileSpec_GetFileName(filespec, &str);
wprintf(L"The file name is \"%ls\".\n\n", str.str);
swprintf_s(output_file, MAX_FILE_PATH, L"%lsaf_4.txt", output_directory);
FSDK_FileSpec_ExportToFile(filespec, output_file, &return_result);
}
// Save PDF file
swprintf_s(output_file, MAX_FILE_PATH, L"%lsassociated_files.pdf", output_directory);
error_code = FSDK_PDFDoc_SaveAs(doc, output_file, e_FSSaveFlagNoOriginal, &return_result);
if (error_code != e_FSErrSuccess) {
printf("Save doc error!\n");
FSDK_PDFDoc_Release(doc);
return 1;
}
FSDK_PDFDoc_Release(doc);
}
FSDK_Library_Release();
return err_ret;
}
Objective-C
#include "FSPDFObjC.h"
FSAssociatedFiles *associated_files = [[FSAssociatedFiles alloc] initWithPdf_doc:doc];
FSPDFDictionary *doc_catalog_dict = [doc getCatalog];
int count = [associated_files getAssociatedFilesCount:doc_catalog_dict];
NSLog(@"The catalog dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
FSFileSpec *filespec = [associated_files getAssociatedFile:doc_catalog_dict index:0];
NSLog(@"The file name is \"%@\".\n\n", filespec.fileName);
[filespec exportToFile:[[NSString alloc] initWithFormat:@"%@af_1.txt", output_directory]];
FSPDFPage *page = [doc getPage:0];
FSPDFDictionary *page_dict = [page getDict];
count = [associated_files getAssociatedFilesCount:page_dict];
NSLog(@"The page dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
filespec = [associated_files getAssociatedFile:page_dict index:0];
NSLog(@"The file name is \"%@\".\n\n", filespec.fileName);
[filespec exportToFile:[[NSString alloc] initWithFormat:@"%@af_2.txt", output_directory]];
FSAnnot *annot = [page getAnnot:0];
FSPDFDictionary *annot_dict = [annot getDict];
count = [associated_files getAssociatedFilesCount:annot_dict];
NSLog(@"The annot dictionary of \"AF_Catalog_Page_Annot.pdf\" has %d associated files.\n", count);
filespec = [associated_files getAssociatedFile:annot_dict index:0];
NSLog(@"The file name is \"%@\".\n\n", filespec.fileName);
[filespec exportToFile:[[NSString alloc] initWithFormat:@"%@af_4.txt", output_directory]];
// Create filespec with 1.txt
FSFileSpec *filespec_txt = [[FSFileSpec alloc] initWithDocument:doc];
filespec_txt.associteFileRelationship = FSAssociatedFilesRelationshipSource;
filespec_txt.fileName = @"1.txt";
FSDateTime *dateTime = [[FSDateTime alloc] initWithYear:2017 month:9 day:15 hour:17 minute:20 second:20 milliseconds:0 utc_hour_offset:8 utc_minute_offset:0];
filespec_txt.description = @"text";
[filespec_txt embed:[input_path stringByAppendingString:@"1.txt"]];
filespec_txt.creationDateTime = dateTime;
filespec_txt.modifiedDateTime = dateTime;
// Associate 1.txt with catalog dictionary.
{
FSPDFObject *catalog_dict = [doc getCatalog];
[associated_files associateFile:catalog_dict file_spec:filespec_txt];
NSLog(@"Associate a text file with catalog dictionary.\n");
FSFileSpec *filespec_catalog = [associated_files getAssociatedFile:catalog_dict index:0];
[filespec_catalog exportToFile:[[NSString alloc] initWithFormat:@"%@catalog.txt", output_directory]];
}
Updated on October 13, 2023