ظهر الاكتشاف بعد ست سنوات من النشر: ثمانية وثلاثون ألف فاتورة مؤرشفة كانت تعلن PDF/A-1b في بيانات XMP الوصفية، وعينة مررت عبر veraPDF فشل معظمها تقريبا — ألوان RGB معتمدة على الجهاز بلا OutputIntent، وخطان غير مضمنين، وأعلام تعليقات توضيحية يحظرها ISO 19005-1. كان التطبيق المولّد قد كتب معرّف المطابقة من دون أن يتحقق يوما من المعيار، وكل نظام لاحق وثق بالوسم. الامتثال المعلن ذاتيا لا يساوي إلا تكلفة كتابته. البديل المتين هو preflight في اللحظة التي يدخل فيها الملف الأرشيف، وتجعل losLab PDF Library (PDFlibPas) ذلك عمليا لأنظمة Delphi و C++Builder ببناء مدققات PDF/A و PDF/UA داخل المكتبة نفسها، بلا خدمة خارجية في المسار.
معياران يفشلان الملفات لأسباب متعاكسة
ISO 19005 (PDF/A) عقد إعادة إنتاج: يجب أن يعرض الملف المطابق بالشكل نفسه بعد عقود، على برنامج لم ير النظام الأصلي قط. لذلك تهاجم قواعده الاعتمادات الخارجية — كل خط مضمّن، واللون مربوط بـ ICC OutputIntent مضمّن أو معبر عنه في فضاءات مستقلة عن الجهاز، ولا تشفير في PDF/A-1، ولا JavaScript، وبيانات XMP متسقة مع قاموس معلومات المستند.
ISO 14289 (PDF/UA) عقد دلالات: يجب أن تستطيع التقنية المساعدة اجتياز المستند بمعنى. تعيش قواعده في طبقة أخرى تماما — شجرة بنية كاملة، ونص بديل للصور، وعنوان مستند مضبوط للعرض، ومستويات عناوين لا تقفز، وعلاقات رؤوس جداول تصمد خارج الشاشة.
المعياران متعامدان، والملفات الخطرة تقع في الوسط. يمكن أن يكون المستند مثاليا للأرشفة وغير قابل للقراءة لقارئ شاشة؛ ويمكن أن يكون المستند موسوما بلا عيب لكنه يشير إلى خط سطح مكتب لن يوجد بعد عشر سنوات. الخطوط التي تحتاج الاثنين — نشر القطاع العام هو المثال القانوني — يجب أن تشغل الفحصين وتوجه النتائج إلى مالكين مختلفين، لأن الخطوط غير المضمنة عيب في كود التوليد بينما النص البديل المفقود يعود إلى من يحافظ على القوالب.
اختيار الجزء مهم بقدر الحكم. PDF/A-1، المتجمد عند PDF 1.4، يرفض الشفافية و JPEG2000 — ميزات يستخدمها إخراج التقارير الحديث بحرية. PDF/A-2 (ISO 19005-2، المبني على ISO 32000-1) يقبل الاثنين وهو الافتراض المنطقي للأرشيفات الجديدة. ويسمح PDF/A-3 إضافة إلى ذلك بملفات مضمنة من أي نوع، وهذا ما تعتمد عليه صيغ الفوترة الإلكترونية المنظمة. فريق ما زال يوحد على PDF/A-1b في 2026 غالبا يرث متطلبا كُتب قبل خمسة عشر عاما، وأرخص إصلاح غالبا هو إعادة التفاوض على الجزء المستهدف بدلا من نزع الشفافية من كل مخطط.
نتائج بنيوية عند وقت الاستقبال
نقطة دخول API المسطحة هي CheckFileCompliance، مع محدد اختبار 1 لـ PDF/A و2 لـ PDF/UA. تعيد مقبض string-list عناصره نتائج فردية، وهذا يجعلها الشكل المناسب لبوابة آلية:
function GateArchiveUpload(Pdf: TPDFlib; const FileName: string): Boolean;
var
ListId, I: Integer;
begin
ListId := Pdf.CheckFileCompliance(FileName, '', 1, 0); // 1 = PDF/A
if ListId = 0 then
begin
// 0 means "no findings" OR "file unreadable" -- disambiguate before passing
Result := Pdf.LastErrorCode = 0;
Exit;
end;
for I := 0 to Pdf.GetStringListCount(ListId) - 1 do
LogFinding(FileName, Pdf.GetStringListItem(ListId, I));
Pdf.ReleaseStringList(ListId);
Result := False;
end;
تفصيلان تنفيذيان يقرران هل يعمل هذا بلا حضور. أولا، تعيد CheckFileCompliance القيمة 0 عندما يكون الملف ممتثلا تماما وعندما لا يمكن فتحه إطلاقا — داخليا، تنتج قائمة نتائج فارغة 0 في الحالتين — لذلك فإن بوابة تقرأ 0 كنجاح ستمرر uploads تالفة مباشرة إلى الأرشيف. ميّز عبر LastErrorCode كما في الأعلى. ثانيا، يعمل المدقق على قارئ streaming في المكتبة لا على نموذج المستند الكامل: يفتح الملف مباشرة بمشاركة قراءة ولا يحتاج إلى LoadFromFile، ولهذا يتعامل مع الملفات متعددة الغيغابايت من دون بناء أشجار كائنات — لكنه سيفشل إذا بقيت عملية أخرى تمسك الملف للكتابة، وهي تحديدا حالة upload قيد التنفيذ. افتح البوابة بعد اكتمال النقل، لا أثناءه.
ينتج throughput من التصميم نفسه. لأن كل فحص يفتح مدخله للقراءة فقط ويشارك الملف للقراءة، يمكن تدقيق corpus بالتوازي طبيعيا عبر خيوط أو عمليات عاملة، نسخة TPDFlib واحدة لكل عامل. مقابض string-list هي المورد الذي يجب الانضباط فيه: كل مقبض غير صفري من CheckFileCompliance يبقى مخصصا حتى ReleaseStringList، وخدمة طويلة العمر تسربها تتدهور ببطء بدلا من أن تفشل بصوت عال.
تقارير للبشر وفروق لبوابات البناء
قوائم النتائج هي الشكل الصحيح للبوابة والشكل الخطأ لبريد يرسل إلى فريق القوالب. تصيّر CreatePreflightReport التحليل نفسه كتقرير قابل للقراءة، وتضيف CreatePreflightReportEx محدد صيغة تقرير، وتكتب SavePreflightReport التقرير إلى القرص كي يشحن داخل حزمة المستند — وهو متطلب تعاقدي في كثير من اتفاقات التسليم الأرشيفي.
أكثر أفراد العائلة استخفافا به هو ComparePreflightReports. نتائج الامتثال سطح regression مثل أي سطح آخر: تعديل قالب، أو خط شركة جديد، أو ترقية مكتبة يمكن أن يضيف نتائج لم تكن موجودة في الإصدار السابق. احتفظ بتقارير golden لمجموعة مستندات ممثلة تحت version control، وأعد توليدها بعد كل تغيير، ودع ComparePreflightReports يحسب delta. فرق فارغ يصبح artifact إصدار؛ ونتيجة مفاجئة تفشل البناء بدلا من أن تفشل التدقيق.
توليد إخراج ينجح من المرة الأولى
يكسب preflight قيمته عند الملفات الداخلة؛ أما المستندات التي ينتجها كودك، فإصلاح النتائج بعد التوليد طريق معكوس. يحمل PDFlibPas نمط توليد لكل معيار، ويمكن تركيب الاثنين:
var
Pdf: TPDFlib;
Diag: WideString;
begin
Pdf := TPDFlib.Create;
try
Pdf.NewDocument;
Pdf.SetPDFAMode(1);
Pdf.LoadOutputIntentProfile('sRGB-IEC61966-2.1.icc', 'RGB');
Pdf.SetPDFUAMode('en-US');
Pdf.SetInformation(1, 'Quarterly Statement'); // /Title: required for PDF/UA
// ... draw tagged content here ...
Diag := Pdf.GetPDFUADiagnostics;
if Diag <> '' then
Writeln('fix before shipping: ', Diag);
Pdf.SaveToFile('statement.pdf');
// the preflight that counts runs on the saved file:
Writeln(Pdf.CreatePreflightReport('statement.pdf', '', 1, 0));
finally
Pdf.Free;
end;
end;
الفخ مختبئ عند الحفظ. عدة إصلاحات مطابقة — فرض علم الطباعة على التعليقات التوضيحية، وكتابة AFRelationship الافتراضي لملفات PDF/A-3 المضمنة، وتطبيع ترتيب tabs وأوصاف حقول النماذج لـ PDF/UA — تطبق أثناء تسلسل المستند، لا عند تفعيل النمط. المستند في الذاكرة ليس مطابق البايتات لما يصل إلى القرص، لذلك حكم preflight الوحيد الذي يهم هو المحسوب من الملف المحفوظ. تحقق من statement.pdf؛ لا تستنتج الامتثال من كائن المستند الموجود في الذاكرة.
سيناريوهات الفواتير التي تضمن XML قابلا للقراءة آليا بجانب المستند المرئي — نمط ZUGFeRD و Factur-X، المبني على PDF/A-3 — يجب أن تضبط علاقة المرفق صراحة عبر SetPDFA3DefaultAFRelationship، لأن ISO 19005-3 يتطلب من كل ملف مضمن أن يعلن دوره بالنسبة إلى المستند.
حكام مستقلون: veraPDF و Acrobat
لا تدع المنتج يصحح واجبه بنفسه. تعطي مدققات PDFlibPas أحكاما سريعة وبنيوية وداخل العملية؛ لكن بوابة الإصدار لدفعات الأرشيف يجب أن تضم مدققا مستقلا. veraPDF هو تنفيذ المرجع المجتمعي لصلاحية PDF/A والأداة التي تسميها معظم الأرشيفات في معايير قبولها؛ وتقدم profiles الخاصة بـ Acrobat preflight رأيا ثالثا مفيدا عندما يختلف أداتان. سجل اسم المدقق وإصداره بجانب كل تقرير محفوظ — ادعاء اجتياز veraPDF لا يعني الكثير من دون معرفة أي veraPDF.
عندما يختلف المدققون، وسيحدث ذلك أحيانا حول أطراف المعايير، صغّر الملف إلى عينة دنيا واحكم وفق نص المعيار لا وفق أي أداة. تستغرق العملية ساعة وغالبا تكشف إما خطأ أداة يستحق الإبلاغ عنه أو بندا قُرئ خطأ ويستحق توثيقه في ملاحظات امتثال الفريق.
المدخلات المشفرة تحتاج قاعدة خاصة. يقبل المدققان معامل كلمة مرور، لكن في PDF/A-1 يكون قاموس التشفير نفسه مخالفة امتثال أصلا — فـ ISO 19005-1 يحظره صراحة — لذلك يمكن رفض submission مشفر قبل أي تحليل أعمق. تدقيق ما يسمح به قاموس التشفير فعلا تمرين منفصل، تغطيه مقالة تدقيق تشفير PDF والأذونات.
نتائج PDF/UA تكاد ترجع دائما إلى كيفية تأليف شجرة البنية؛ وتقنيات tagging مشروحة في بناء أشجار بنية Tagged PDF في Delphi. الأرشيفات التي تتطلب أيضا توقيعات رقمية يجب أن تقرن هذه البوابة بالworkflow في توقيع PAdES والتحقق منه. مرجع API الكامل لـ preflight موجود في صفحة منتج losLab PDF Library for Delphi.