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 实现 ISO 16612-2 附件定义的 PDF/VT-2s 传输方式:PDF/VT 文档连同其引用的可复用 PDF 内容和 ICC 配置文件被打包为单个 MIME multipart 流
与写入独立 PDF/VT-1 文件的 TPdf.SaveAsPdfVT 路径不同,本单元完全在字节流上操作,从不加载 pdfium.dll,因此可以在无界面服务器和批处理管线中运行
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,解析到较早的 ICC MIME 部分
| Value | MIME role |
|---|---|
vtckInlinePdf | 以内联 application/pdf 部分携带的 PDF/VT 文档;至少需要一个 |
vtckAttachmentPdf | 由内联文档引用的可复用 PDF 内容部分,以带文件名的 attachment 形式携带 |
vtckIccProfile | ICC 配置文件部分(application/vnd.iccprofile),作为带文件名的附件提供 |
| Type | Purpose |
|---|---|
TPdfVT2sChunks | 提供给 BuildPdfVT2sStream 的有序 MIME 块动态数组 |
TAnsiStrings | 验证内联 PDF 中的外部文件引用时使用的动态文件名数组 |
TPdfVT2sValidationIssues | 验证返回的 TPdfVT2sValidationIssue 发现项集合 |
TPdfVTPrintingConditionSource | 配置文件证据的来源:未解析时为 vtpcsNone,内嵌 DestOutputProfile 流为 vtpcsEmbeddedProfile,从 ICC MIME 部分解析的 DestOutputProfileRef 为 vtpcsMimeProfile |
TPdfVTPrintingConditionEvidence | 每个部分的 PDF/VT 与 PDF/X 分类、OutputIntent、配置文件来源、标识、摘要、ICC 头和 DPart 事实 |
TPdfVT2sValidationReport | InspectPdfVT2sStream 返回的详细结果,不改变旧版结果的布局 |
| Value | Reported when |
|---|---|
vtmviNotMultipart | 流不是 multipart MIME 容器 |
vtmviMissingStreamVersion | 缺少必需的 PDF/VT StreamVersion 头 |
vtmviStreamVersionValue | StreamVersion 值不是预期的 1 |
vtmviStreamVersionAfterCt | StreamVersion 出现在 Content-Type 行之后而不是之前 |
vtmviMissingBoundary | 缺少 Content-Type 的 boundary 参数 |
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 部分有零个或多个权威的 GTS_PDFX OutputIntent |
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 与完整 ICC 文件的 MD5 不同 |
vtmviIccVersionMismatch | 声明的四个 ICCVersion 字节与 ICC 头第 8 至 11 字节不同 |
vtmviIccColorSpaceMismatch | ProfileCS 与 ICC 头第 16 至 19 字节不同,或不是 GRAY、RGB 或 CMYK |
vtmviIccProfileNameMismatch | ProfileName 与任何有效的 profileDescriptionTag 区域设置值都不匹配 |
vtmviPrintingConditionUnresolved | 无法解析权威的 OutputIntent、标识符或外部 ICC 依赖 |
vtmviPrintingConditionMismatch | PDF/VT 部分在 OutputConditionIdentifier、RegistryName 的存在或取值、或印刷色彩空间上不一致 |
vtmviIccDeviceClassMismatch | 内嵌或外部目标配置文件不是输出设备 prtr 配置文件 |
BuildPdfVT2sStream 产生的流上进行往返测试时调用 ValidatePdfVT2sStream,或在处理外部制作的 PDF/VT-2s 容器之前调用TPdfVT2sValidationResult.IsCompliant 仅在 Issues 集合为空时返回 True
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;