Inom företagsutskrifter, arkivering och arbetsflöden för dokumentefterlevnad kan en PDF-fil inte bara "renderas". Den måste granskas. En PDF kan innehålla oplattade (unflattened) transparensgrupper som kraschar äldre rasterbildprocessorer (RIP), inbäddat JavaScript som utgör en säkerhetsrisk, eller lågupplösta bilder som kommer att se hemska ut när de skrivs ut i 300 DPI.
Denna process att inspektera en PDF innan den går in i ett produktionsarbetsflöde kallas Preflighting. I den här artikeln kommer vi att utforska hur man bygger ett automatiserat verktyg för preflight och riskgranskning i Delphi genom att utnyttja PDFiums lågnivåkapacitet för tolkning.
Viktiga Preflight-kontroller
En standardriskgranskning letar vanligtvis efter följande element inuti en PDF:
- Interaktiva element: JavaScript-händelser, Launch-händelser (körning av externa program) och AcroForms.
- Resursmått: Förekomst av lågupplösta bilder eller saknade inbäddade teckensnitt.
- Säkerhetsstatus: Dokumentkryptering, lösenordskrav och åtkomstbehörigheter (t.ex. att utskrift är inaktiverat).
- Dokumentstandarder: Validering av PDF/A- eller PDF/X-efterlevnadsmarkörer i dokumentets metadata.
Extrahera PDF-metadata och kommentarer med PDFium
PDFium tillhandahåller ett robust C API som Delphi kan använda. För att utföra en preflight-granskning renderar vi inte bara sidan; vi går igenom PDF-objektträdet. Låt oss titta på hur man itererar genom dokumentsidorna och inspekterar kommentarer (annotations) för att hitta potentiellt riskfyllda JavaScript-händelser.
uses
System.SysUtils, pdfium_lib;
procedure AuditPdfSecurity(const FileName: string);
var
Doc: FPDF_DOCUMENT;
PageCount, i, j: Integer;
Page: FPDF_PAGE;
AnnotCount: Integer;
Annot: FPDF_ANNOTATION;
AnnotSubType: FPDF_ANNOTATION_SUBTYPE;
Action: FPDF_ACTION;
ActionType: ULONG;
begin
FPDF_InitLibrary();
try
// Load the document without a password
Doc := FPDF_LoadDocument(PAnsiChar(AnsiString(FileName)), nil);
if Doc = nil then
raise Exception.Create('Failed to load document or password required.');
try
PageCount := FPDF_GetPageCount(Doc);
Writeln(Format('Auditing %d pages...', [PageCount]));
for i := 0 to PageCount - 1 do
begin
Page := FPDF_LoadPage(Doc, i);
if Page <> nil then
begin
AnnotCount := FPDFPage_GetAnnotCount(Page);
for j := 0 to AnnotCount - 1 do
begin
Annot := FPDFPage_GetAnnot(Page, j);
if Annot <> nil then
begin
AnnotSubType := FPDFAnnot_GetSubtype(Annot);
// Check for Link Annotations that might have malicious actions
if AnnotSubType = FPDF_ANNOT_LINK then
begin
Action := FPDFAnnot_GetLinkAction(Annot);
if Action <> nil then
begin
ActionType := FPDFAction_GetType(Action);
// 2 represents PDFACTION_URI, 3 represents PDFACTION_SOUND, 4 represents PDFACTION_MOVIE
// We specifically look out for PDFACTION_LAUNCH or PDFACTION_JAVA_SCRIPT
if (ActionType = PDFACTION_JAVA_SCRIPT) or (ActionType = PDFACTION_LAUNCH) then
begin
Writeln(Format('WARNING: Malicious action detected on page %d', [i + 1]));
end;
end;
end;
FPDFPage_CloseAnnot(Annot);
end;
end;
FPDF_ClosePage(Page);
end;
end;
finally
FPDF_CloseDocument(Doc);
end;
finally
FPDF_DestroyLibrary();
end;
end;
Kontrollera bildupplösning
Ett annat kritiskt preflight-steg för utskriftsarbetsflöden är att säkerställa att ingen bild hamnar under ett specifikt DPI-gränsvärde. PDFium låter dig extrahera bildobjekt direkt från sidströmmen. Genom att dividera pixeldimensionerna för den extraherade bilden med de fysiska dimensioner (i punkter) som den upptar på PDF-sidan, kan du beräkna det effektiva DPI-värdet.
procedure AuditPageImages(Page: FPDF_PAGE);
var
ObjCount, i: Integer;
PageObj: FPDF_PAGEOBJECT;
ImgWidth, ImgHeight: Integer;
begin
ObjCount := FPDFPage_CountObjects(Page);
for i := 0 to ObjCount - 1 do
begin
PageObj := FPDFPage_GetObject(Page, i);
if FPDFPageObj_GetType(PageObj) = FPDF_PAGEOBJ_IMAGE then
begin
FPDFImageObj_GetBitmap(PageObj); // Returns an FPDF_BITMAP you can inspect
// Retrieve metadata using FPDFImageObj_GetImageMetadata
// Calculate effective DPI based on quad coordinates
end;
end;
end;
Integrera med PDFium Component
Att bygga en robust preflight-motor från grunden med hjälp av det råa PDFium C API:et kräver betydande mängder kod och djup kunskap om PDF-specifikationen. Att använda en wrapper förenklar detta enormt. Med en Delphi-wrapper på hög nivå kan du omvandla komplexa C-pekariterationer till ren, objektorienterad kod.
Genom att automatisera preflight-fasen förhindrar du att dåliga filer stoppar upp din produktionspipeline, vilket sparar både tid och renderingsresurser.
Obs: Avancerade funktioner för PDF-tolkning och preflight stöds fullt ut av PDFium Component.