TVt2sChunkKind = (vtckInlinePdf, vtckAttachmentPdf, vtckIccProfile);
TPdfVT2sChunk = record
Kind: TVt2sChunkKind;
Bytes: TBytes;
FileName: AnsiString;
end;
TPdfVT2sChunks = array of TPdfVT2sChunk;
TAnsiStrings = array of AnsiString;
TPdfVT2sValidationResult = record
Issues: TPdfVT2sValidationIssues;
function IsCompliant: Boolean;
end;
TPdfVTPrintingConditionSource = (vtpcsNone, vtpcsEmbeddedProfile, vtpcsMimeProfile);
TPdfVTPrintingConditionEvidence = record
PartIndex: Integer;
Conformance: TPdfVTConformance;
PdfXVersion: AnsiString;
OutputIntentObjectNumber: Integer;
OutputConditionIdentifier: AnsiString;
RegistryName: AnsiString;
Source: TPdfVTPrintingConditionSource;
ProfileFileName: AnsiString;
ProfileName: AnsiString;
ProfileColorSpace: AnsiString;
ProfileByteSize: Int64;
ProfileMd5: string;
ProfileSha256: string;
ProfileVersion: string;
ProfileDeviceClass: string;
ProfilePcs: string;
ProfileComponentCount: Integer;
Resolved: Boolean;
ProfileValid: Boolean;
DPart: TPdfVTDPartEvidence;
end;
TPdfVT2sValidationReport = record
Validation: TPdfVT2sValidationResult;
PrintingConditions: TPdfVTPrintingConditionEvidenceArray;
end;
procedure BuildPdfVT2sStream(const Chunks: TPdfVT2sChunks; Dest: TStream);
function ValidatePdfVT2sStream(Source: TStream): TPdfVT2sValidationResult;
function InspectPdfVT2sStream(Source: TStream): TPdfVT2sValidationReport;
FPdfPdfvtMime реализует транспорт PDF/VT-2s, определённый в приложении ISO 16612-2, где документ PDF/VT вместе со ссылочным повторно используемым содержимым PDF и профилем ICC упаковывается в один поток MIME multipart
В отличие от пути TPdf.SaveAsPdfVT, записывающего автономный файл PDF/VT-1, этот модуль работает исключительно с байтовыми потоками и никогда не загружает pdfium.dll, поэтому может выполняться в headless-серверах и пакетных конвейерах
BuildPdfVT2sStream собирает фрагменты по порядку и выдаёт заголовок StreamVersion, границы частей и заголовки Content-Type / Content-Disposition каждой части; ValidatePdfVT2sStream разбирает существующий поток обратно и сообщает структурные отклонения, отклонения условий печати и ICC типизированным множеством проблем
InspectPdfVT2sStream возвращает тот же результат совместимости плюс свидетельства по каждой части PDF/VT, включая соответствие PDF/VT, базу PDF/X, идентичность OutputIntent, происхождение профиля, MD5 и SHA-256, сырые метаданные ICC, а также счётчики страниц DPart и записей получателей
Каждая часть PDF сначала классифицируется с ValidatePdfVTCompliance; повторно используемые вложения только PDF/X остаются допустимыми целями ссылок, но исключаются из иерархии PDF/VT и сравнений условий печати
Упаковка профиля следует за базой файла: PDF/VT-1 с PDF/X-4 и PDF/VT-2 с PDF/X-5g используют встроенный DestOutputProfile, а PDF/VT-2 с PDF/X-4p или PDF/X-5pg — DestOutputProfileRef, разрешаемый в более раннюю часть MIME с ICC
| Value | MIME role |
|---|---|
vtckInlinePdf | Документ PDF/VT, переносимый как встроенная часть application/pdf; требуется минимум одна |
vtckAttachmentPdf | Часть повторно используемого содержимого PDF, на которую ссылается встроенный документ, переносимая как attachment с именем файла |
vtckIccProfile | Часть профиля ICC (application/vnd.iccprofile), передаваемая как вложение с именем файла |
| Type | Purpose |
|---|---|
TPdfVT2sChunks | Динамический массив упорядоченных MIME-фрагментов, передаваемый BuildPdfVT2sStream |
TAnsiStrings | Динамический массив имён файлов, используемый при проверке ссылок на внешние файлы во встроенном PDF |
TPdfVT2sValidationIssues | Множество находок TPdfVT2sValidationIssue, возвращаемое проверкой |
TPdfVTPrintingConditionSource | Происхождение свидетельств профиля: vtpcsNone, когда не разрешено, vtpcsEmbeddedProfile для встроенного потока DestOutputProfile, vtpcsMimeProfile для DestOutputProfileRef, разрешённого из части MIME с ICC |
TPdfVTPrintingConditionEvidence | Классификация PDF/VT и PDF/X по каждой части, OutputIntent, источник профиля, идентичность, дайджест, заголовок ICC и факты DPart |
TPdfVT2sValidationReport | Подробный результат, возвращаемый InspectPdfVT2sStream, без изменения прежней раскладки результата |
| Value | Reported when |
|---|---|
vtmviNotMultipart | Поток не является MIME-контейнером multipart |
vtmviMissingStreamVersion | Отсутствует требуемый заголовок PDF/VT StreamVersion |
vtmviStreamVersionValue | Значение StreamVersion не равно ожидаемому 1 |
vtmviStreamVersionAfterCt | StreamVersion идёт после строки Content-Type, а не перед ней |
vtmviMissingBoundary | Отсутствует параметр boundary в Content-Type |
vtmviNoInlinePdf | В потоке нет ни одной встроенной части PDF/VT |
vtmviInlinePdfNotPdfVT | Встроенная часть не объявлена как PDF/VT |
vtmviIccProfileBadDisposition | Часть профиля ICC не является вложением |
vtmviAttachmentMissingFilename | Часть-вложение не имеет требуемого имени файла |
vtmviInlineHasFilename | Встроенная часть PDF несёт имя файла, что не допускается |
vtmviNodeNameListMismatch | Два файла PDF/VT в потоке выдают разные значения NodeNameList |
vtmviRecordLevelMismatch | Уровни записей DPart не согласованы по контейнеру |
vtmviForwardReference | Вложение упоминается до того, как появляется в потоке |
vtmviBoundaryInvalidChar | Строка boundary содержит символы, не допустимые RFC 2046 |
vtmviDuplicateFilename | Два MIME-вложения выдают одно и то же имя файла с учётом регистра |
vtmviOutputIntentAmbiguous | Часть PDF имеет ноль или несколько авторитетных OutputIntent GTS_PDFX |
vtmviOutputProfilePackagingMismatch | OutputIntent имеет обе формы профиля, ни одной либо форму, несовместимую с базой PDF/X-4, PDF/X-4p, PDF/X-5g или PDF/X-5pg |
vtmviOutputProfileReferenceInvalid | DestOutputProfileRef опускает требуемые метаданные или файловую спецификацию URL либо использует запрещённый ColorantTable |
vtmviReferencedPartWrongType | Упомянутое имя файла разрешается в часть MIME, не являющуюся профилем ICC |
vtmviIccProfileInvalid | Заголовок ICC, объявленный размер, подпись, таблица тегов или поддерживаемое пространство процессных цветов некорректны |
vtmviIccChecksumMismatch | Декодированная 16-байтовая CheckSum отличается от MD5 полного файла ICC |
vtmviIccVersionMismatch | Объявленные четыре байта ICCVersion отличаются от байтов 8–11 заголовка ICC |
vtmviIccColorSpaceMismatch | ProfileCS отличается от байтов 16–19 заголовка ICC либо не является GRAY, RGB или CMYK |
vtmviIccProfileNameMismatch | ProfileName не совпадает ни с одним корректным значением локали profileDescriptionTag |
vtmviPrintingConditionUnresolved | Авторитетный OutputIntent, идентификатор или внешняя зависимость ICC не могут быть разрешены |
vtmviPrintingConditionMismatch | Части PDF/VT расходятся в OutputConditionIdentifier, наличии или значении RegistryName либо пространстве процессных цветов |
vtmviIccDeviceClassMismatch | Встроенный или внешний целевой профиль не является профилем выходного устройства prtr |
ValidatePdfVT2sStream на любом потоке, созданном BuildPdfVT2sStream при проверке прямого и обратного преобразования, либо на внешних контейнерах PDF/VT-2s перед обработкойTPdfVT2sValidationResult.IsCompliant возвращает True, только когда множество Issues пусто
var Chunks: TPdfVT2sChunks;
begin
SetLength(Chunks, 2);
Chunks[0].Kind := vtckIccProfile;
Chunks[0].FileName := 'profile.icc';
Chunks[0].Bytes := IccBytes;
Chunks[1].Kind := vtckInlinePdf;
Chunks[1].Bytes := InlinePdfBytes;
BuildPdfVT2sStream(Chunks, MimeStream);
end;