L_LTFIL_API L_INT L_ReadFileAttachments(pszFile, ppAttachments, pLoadOptions, pInfo)
Reads the properties of the attachments embedded in the specified file.
Character string containing the name of the owner file that may contain embedded attachments.
Pointer to a variable that will be populated with the properties of any attachments found.
Pointer to optional extended load options. Pass NULL to use the default load options. Refer to L_LoadFile for more information.
Pointer to a FILEINFO structure. This structure may contain file information used in loading an image, or it may be updated with information about the file being loaded.
This value can be NULL.
Refer to L_LoadFile for more information.
Value | Meaning |
---|---|
SUCCESS | The function was successful. |
ERROR_NO_ATTACHMENTS | The file is a format that supports attachments, such as PDF, but no attachments were found. |
ERROR_FEATURE_NOT_SUPPORTED | The file is a format that does not support attachments (such as PNG or BMP), or LEADTOOLS does not support reading attachments of this type of format. |
ERRORPDFINVALID_PASSWORD | The owner file is encrypted. Pass the correct password using L_SetPDFOptions and try again. |
< 1 | An error occurred. Refer to Return Codes. |
Applications can read the properties of the attachments included in a file by performing the following steps:
L_FILEATTACHMENTS
pointer.L_FILEATTACHMENTS
.L_ReadFileAttachments returns the following values:
SUCCESS
: If the format of the owner file supports attachments (such as PDF), and the file contains one or more embedded attachments, ppAttachments will define a pointer to the structure containing the attachment's properties. Be sure the application calls L_FreeAttachments when the data is no longer needed.
ERROR_NO_ATTACHMENTS
: If the file is a format that supports attachments (such as PDF), but no attachments were found, ppAttachments will be set to NULL.
ERROR_FEATURE_NOT_SUPPORTED
: If the file is a format that does not support attachments (such as PNG or BMP), or LEADTOOLS does not support reading attachments of this type of format, ppAttachments will be set to NULL.
The number of attachment items returned by this method is the same as the FILEINFO.nAttachmentCount
value of the object returned by L_FileInfo.
Each L_FILEATTACHMENT contains properties of the attachment such as its pszFileName
, uFileLength
, and other information provided by the owner document.
Use L_ExtractAttachment to extract the binary content of the attachment file into an output disk file or stream for further processing (for example, by calling L_FileInfo or L_LoadBitmap).
LEADTOOLS supports reading the attachments embedded in the following file format:
PDF files support embedded attachments of any number and file format (such as PDF, TIFF, XML, etc). PDF files can also be created as a portfolio which contains multiple files assembled into an integrated unit. In these types of documents, the file contains a single generic help page with text such as "For the best experience, open this PDF portfolio in a compatible viewer", as well as any number of attachments and a schema to control how to view the document. The value of FILEINFO.uFlags
will contain FILEINFO_PORTFOLIO
if the file is a PDF portfolio, and it is up to the application to specify any further handling of the file.
Win32, x64, Linux.
This example will do the following:
// This example will do the following :
// -Show information on all the attachments embedded in the file
// - Extract the attachment files into an output directory
// - Show the file format and page count of each attachment
L_INT ReadFileAttachmentsExample(L_TCHAR* fileName, L_TCHAR* outputDir)
{
L_INT attachmentCount;
// Get information on the owner file
// This step is optional if we are not interested in determining whether the owner file format
// or whether it is a PDF portfolio.
FILEINFO fileInfo;
L_INT ret = L_FileInfo(fileName, &fileInfo, sizeof(FILEINFO), FILEINFO_TOTALPAGES, NULL);
if(ret != SUCCESS)
return ret;
printf("Information\n");
printf("Format:%d\n", fileInfo.Format);
// If PDF, check if it is portfolio
if(fileInfo.Format == FILE_RAS_PDF)
printf("IsPortfolio:%d\n", (fileInfo.Flags & FILEINFO_PORTFOLIO) == FILEINFO_PORTFOLIO);
attachmentCount = fileInfo.nAttachmentCount;
printf("Attachments:%d\n", fileInfo.nAttachmentCount);
// Read the properties of the attachments embedded in this file
L_FILEATTACHMENTS* attachments = NULL;
ret = L_ReadFileAttachments(fileName, &attachments, NULL, NULL);
if(ret == ERROR_FEATURE_NOT_SUPPORTED)
{
// This means the format of the file does not support attachments
printf("WARNING: attachments is not supported by this file format\n");
return SUCCESS;
}
else if(ret == ERROR_NO_ATTACHMENTS)
{
// This means the format of the file supports attachments but we did not find any in the file
printf("WARNING: file has no attachments\n");
return SUCCESS;
}
else if(ret != SUCCESS)
{
// Any other error is not expected
printf("ERROR: %d\n", ret);
return ret;
}
// Sanity check
assert(attachments->uItemCount == attachmentCount);
// Create the output directory if it does not exist
CreateDirectory(outputDir, NULL);
LOADFILEOPTION loadFileOption;
L_GetDefaultLoadFileOption(&loadFileOption, sizeof(LOADFILEOPTION));
// Extract the attachments
for(L_UINT attachmentIndex = 0; attachmentIndex < attachments->uItemCount && ret == SUCCESS; attachmentIndex++)
{
// Get the current attachment
const L_FILEATTACHMENT* attachment = (const L_FILEATTACHMENT*)((const L_UCHAR*)attachments->pItems + (attachments->uItemStructSize * attachmentIndex));
// Get the output file name
L_TCHAR outputFileName[MAX_PATH] = { 0 };
wcscat(outputFileName, outputDir);
size_t len = wcslen(outputFileName);
if(outputFileName[len - 1] != '\\')
wcscat(outputFileName, L_TEXT("\\"));
wcscat(outputFileName, attachment->pszFileName);
wprintf(L_TEXT("Extracting attachment to output file: %s\n"), outputFileName);
// Set the attachment number to extract
loadFileOption.nAttachment = (L_INT)attachment->uAttachmentNumber;
// Extract it
ret = L_ExtractAttachment(fileName, NULL, 0, &loadFileOption, NULL, 0, outputFileName, NULL, NULL);
if(ret == SUCCESS)
{
// Show information on this attachment. Notice that this might fail if the attachment
// is not a valid image file format.
memset(&fileInfo, 0, sizeof(FILEINFO));
ret = L_FileInfo(outputFileName, &fileInfo, sizeof(FILEINFO), FILEINFO_TOTALPAGES, NULL);
if(ret == SUCCESS)
{
printf(" attachment format is %d and has %d pages\n", fileInfo.Format, fileInfo.TotalPages);
}
else
{
printf(" attachment format could not be obtained, error %d\n", ret);
ret = SUCCESS; // Swallow this error
}
}
}
// Free the attachments
L_FreeAttachments(attachments);
return ret;
}
// This sample shows how to load an encrypted attachment contained in an encrypted owner file
// The PDF portfolio file (the owner) uses the password 'pass'
// The attachment (the embedded file) uses a different password: 'pass1'
// The operation requires two passwords, so you will need to use two steps:
// 1) Extract the attachment using the owner password (pass)
// 2) Load the image from the attachment buffer using the attachment password (pass1)
L_INT ReadEncryptedFileAttachmentsExample(L_TCHAR* fileName, pBITMAPHANDLE pBitmap)
{
LOADFILEOPTION loadFileOption;
L_GetDefaultLoadFileOption(&loadFileOption, sizeof(LOADFILEOPTION));
loadFileOption.nAttachment = 1;
FILEPDFOPTIONS pdfOptions = {sizeof(FILEPDFOPTIONS)};
L_GetPDFOptions(&pdfOptions, sizeof(FILEPDFOPTIONS));
strcpy_s((char *)pdfOptions.szPassword, _countof(pdfOptions.szPassword), "pass1"); // try first the password for the attachment (pass1)
L_SetPDFOptions(&pdfOptions);
// Try to load the image stored in attachment 1 using the password for the owner file - should fail
L_INT nRet = L_LoadFile(fileName, pBitmap, sizeof(BITMAPHANDLE), 0, ORDER_BGRORGRAY, LOADFILE_ALLOCATE | LOADFILE_STORE, NULL, NULL, &loadFileOption, NULL);
assert(nRet == ERROR_PDF_INVALID_PASSWORD);
if(nRet == ERROR_PDF_INVALID_PASSWORD)
{
strcpy_s((char *)pdfOptions.szPassword, _countof(pdfOptions.szPassword), "pass"); // use the password for the owner file
L_SetPDFOptions(&pdfOptions);
L_UCHAR *pBuffer = NULL;
L_SIZE_T uBufferSize = 0;
// Extract attachment 1 (= loadFileOption.PageNumber) to a memory buffer.
// L_ExtractAttachment will allocate the buffer and store its pointer in pBuffer.
// The buffer size will be stored in uBufferSize
// We will need to free the buffer using L_FreeBuffer when we do not need it anymore.
nRet = L_ExtractAttachment(fileName, NULL, NULL, &loadFileOption, NULL, 0, NULL, &pBuffer, &uBufferSize);
if(nRet != SUCCESS)
return nRet;
// Try loading the attachment without submitting the correct password. This operation should fail
nRet = L_LoadMemory(pBuffer, pBitmap, sizeof(BITMAPHANDLE), 0, ORDER_BGRORGRAY, LOADFILE_ALLOCATE | LOADFILE_STORE, NULL, NULL, uBufferSize, NULL, NULL);
assert(nRet == ERROR_PDF_INVALID_PASSWORD);
if(nRet == ERROR_PDF_INVALID_PASSWORD)
{
// use the password for the attachment file.
strcpy_s((char *)pdfOptions.szPassword, _countof(pdfOptions.szPassword), "pass1");
L_SetPDFOptions(&pdfOptions);
// It is not necessary to pass a LOADFILEOPTION structure anymore, since the main image is being loaded from the attachment.
nRet = L_LoadMemory(pBuffer, pBitmap, sizeof(BITMAPHANDLE), 0, ORDER_BGRORGRAY, LOADFILE_ALLOCATE | LOADFILE_STORE, NULL, NULL, uBufferSize, NULL, NULL);
}
L_FreeBuffer(pBuffer);
}
return nRet;
}