ConvertToPDFA는 한 번의 호출로 일반 문서를 보존용 문서로 바꿉니다. 선택한 파트가 금지하는 것을 제거하고, 파트가 요구하는 것을 추가하고, 문서가 주장하는 파트를 명시한 뒤 결과를 검사합니다. 주장은 검사가 통과할 때만 충족된 것으로 보고되며, GetPDFAConversionReport는 무엇이 이루어졌고 무엇이 여전히 길을 막고 있는지 나열합니다
이 마지막 속성이 숙고할 가치가 있는 설계 결정입니다. 검사 없이 주장을 찍어 넣는 변환기는 아예 변환기가 없는 것보다 못합니다. 보존용이라고 말하면서 그렇지 않은 파일이 그것을 잡았을 시스템을 그대로 통과하기 때문입니다. 실패는 수년 뒤 감사에서, 누구도 다시 만들 수 없는 문서에서 드러납니다
왜 올바른 PDF처럼 보이는 파일이 PDF/A 검사에 걸리는가
대부분은 PDF가 누가 작성했는지 말하는 두 곳이 서로 다르기 때문입니다. 검증기는 문서 정보 딕셔너리와 XMP 패킷을 모두 읽고 둘이 다른 파일을 거부합니다. 이 점에서 실패하는 대부분의 파일은 단순히 XMP 절반을 전혀 작성하지 않았을 뿐입니다
RepairDocumentMetadata는 둘을 일치시키고 복구한 항목 수를 반환합니다. 한쪽만 값을 가질 때는 다른 쪽이 그것으로 채워지므로 이미 기록된 것은 아무것도 버려지지 않습니다. 어느 복사본이 권위 있는지 결정할 필요가 없는데, 실제로는 한 복사본이 비어 있기 때문입니다
같은 호출에 두 번째 복구가 있어 더 미묘한 사례를 잡습니다. PDF/A 모드로 설정된 문서는 표준 식별자를 잃었을 때 복구되는데, 이는 호출자가 자체 XMP 패킷을 제공할 때마다 발생합니다. 이 식별자가 없으면 검증기는 파일을 일반 PDF로 읽고 주장된 파트의 모든 규칙을 미충족으로 보고합니다. 작은 원인 하나가 눈에 띄는 실패를 만들어내는 사례입니다
var
Lib: TPDFlib;
Repaired: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('incoming.pdf', '');
Repaired := Lib.RepairDocumentMetadata;
Log(Format('%d metadata entries brought into agreement', [Repaired]));
Lib.SaveToFile('incoming-fixed.pdf');
finally
Lib.Free;
end;
end;
변환 전에 파트 선택하기
SetPDFAMode와 ConvertToPDFA는 같은 모드 번호 체계를 공유하며, 그중 세 값은 최근 것입니다. 모드 9는 PDF 2.0 위에 구축된 파트인 PDF/A-4입니다. 모드 10은 3D와 리치 미디어를 추가로 허용하는 PDF/A-4e이고, 모드 11은 임의 형식의 임베드 파일을 허용하는 PDF/A-4f입니다
파트 4는 이전 파트와 다른 방식으로 자신을 식별합니다. 파트 번호와 그 파트가 발행된 연도로 식별하며, 일반 PDF/A-4에는 적합도 글자가 없고 두 확장에는 E 또는 F 글자가 붙습니다. 검사는 파트 4를 인식하고, 그 파일을 1.7이 아닌 PDF 2.0 기준으로 판정하며, 개정 연도를 명시하지 않은 파트 4 파일을 보고합니다
파트 4 문서의 모든 임베드 파일은 파트 3과 파트 4 모두 요구하듯 문서와 어떤 관계인지 명시합니다. 이것이 일반 첨부파일을 걸리게 만들던 규칙입니다. 관계는 첫 번째 이후의 첨부파일에만 기록되고 마지막에는 결코 기록되지 않았으므로, 단일 첨부파일을 가진 문서가 흔한 사례임에도 아무 관계도 담지 못해 정확히 그 지점에서 검증에 실패했습니다
var
Verdict: Integer;
begin
Lib.LoadFromFile('report.pdf', '');
Verdict := Lib.ConvertToPDFA(9); // 9 = PDF/A-4, 10 = 4e, 11 = 4f
Memo1.Lines.Text := Lib.GetPDFAConversionReport;
if Verdict = 1 then
Lib.SaveToFile('report-pdfa4.pdf')
else
Log('conversion incomplete - see the report for what stands in the way');
end;
변환 보고서의 용도
다음에 무엇을 할지 결정하는 데 있습니다. 성공한 변환은 보고서가 필요 없지만, 실패한 변환이야말로 보고서가 존재하는 전체 이유입니다. 일부 장애물은 변환기가 제거할 수 있고 일부는 그럴 수 없습니다. 암호화, 의미를 담은 금지된 콘텐츠, 기계 어디에도 존재하지 않는 폰트 프로그램이 그것입니다. 보고서는 이루어진 일과 남은 일을 구분하며, 변환 실패라는 말을 하나의 작업 항목으로 바꿉니다
판정을 배치 파이프라인의 게이트로 취급하십시오. 변환하고, 판정을 읽고, 파일을 분배합니다. 통과한 것은 보관하고, 나머지는 보고서를 첨부하여 담당자 큐에 넣습니다. 해서는 안 될 일은 실패한 변환의 출력이 입력보다 나아 보인다고 해서 보관소에 넣는 것입니다. 그 파일은 이제 검사가 확인하기를 거부한 주장을 담고 있습니다
파일이 이미 담고 있는 표식 읽기
무엇이든 변환하기 전에 문서가 자신에 대해 무엇이라 말하는지 알아야 합니다. 기존 표준 표식을 읽을 수 없는 PDF/A 검사는 선언과 무관하게 모든 파일을 파트 1 기준으로 판정합니다. 즉 완벽하게 유효한 PDF/A-2나 PDF/A-3 문서가 표식이 없는 것으로, 그리고 버전이 너무 높은 것으로 보고됩니다. 사실과 정반대입니다
표식은 생성자가 XMP 요소로 썼든 속성으로 썼든 읽습니다. 두 형태 모두 일반적인 XMP이며, 한쪽만 받아들이면 다른 생성자의 파일이 표식 없는 것으로 보입니다. 다른 곳에서는 검증되는 문서가 여러분의 파이프라인에서 실패하는 이유를 궁금해했다면, 여기가 먼저 살펴볼 만한 곳입니다
보존 전에 살균, 그리고 알아둘 만한 버그
보존 변환과 살균은 함께 실행되는 경우가 많습니다. 보안 정책이 제거하길 원하는 콘텐츠와 PDF/A가 금지하는 콘텐츠가 크게 겹치기 때문입니다. SanitizeDocument는 JavaScript를 제거하며, 마지막 스크립트를 제거하면 그것이 남기는 빈 이름 트리도 함께 제거합니다. 그렇지 않으면 이 트리가 문서가 스크립트를 담고 있었다고 리더에게 계속 알릴 것입니다
두 번째 절반은 어려운 방식으로 배웠습니다. 패키지 목록의 오프바이원 오류로 인해 살균은 스크립트를 제거한다고 보고하면서도 실제로는 아무것도 제거하지 않았고, 살균된 문서가 열릴 때 여전히 스크립트를 실행했습니다. 이 글 전체가 기반을 두는 일반 원칙에 대한 좋은 논증입니다. 라이브러리뿐 아니라 여러분의 파이프라인에서도 작업을 신뢰하기보다 결과를 검증하십시오
주변 보존 작업은 PDF/A와 PDF/UA 프리플라이트, 진정한 교정과 콘텐츠 제거, Factur-X를 위한 PDF/A-3 XMP 확장 스키마 산책문을 보십시오. 마지막은 보존된 문서가 구조화된 청구 데이터도 담을 때 메타데이터 측면을 다룹니다
PDFlibPas는 Delphi, C++Builder, Lazarus를 위한 네이티브 Pascal PDF 라이브러리이므로 변환, 복구, 검증이 모두 체인에 외부 도구 없이 여러분의 프로세스 안에서 일어납니다. 지원되는 PDF/A 파트와 플랫폼은 PDFlibPas 제품 페이지를 보십시오