إضافة باركود PDF جافا – التوقيع والتحقق مع GroupDocs
إذا كنت بحاجة إلى طريقة سريعة ومرئية لتوسيم المستندات في سير العمل الداخلي، فإن إضافة باركود إلى ملف PDF باستخدام جافا هي حل مثالي. باستخدام GroupDocs.Signature، يمكنك تضمين، والتحقق، والبحث، وتحديث، وحذف توقيعات الباركود دون العبء المرتبط بالتوقيعات الرقمية الكاملة القائمة على PKI. يشرح هذا الدليل كل خطوة، من إعداد البيئة إلى أفضل الممارسات الجاهزة للإنتاج.
إجابات سريعة
- ما المكتبة التي تضيف باركود إلى ملفات PDF في جافا؟ GroupDocs.Signature for Java.
- هل يمكنني توقيع PDF وWord والصور؟ نعم – يدعم API أكثر من 30 تنسيقًا.
- هل أحتاج إلى ترخيص للتطوير؟ الترخيص المؤقت لمدة 30 يومًا مجاني؛ الترخيص الكامل مطلوب للإنتاج.
- كم عدد أسطر الكود المطلوبة لتوقيع PDF؟ سطران فقط: إنشاء كائن
Signatureواستدعاءsign. - هل التحقق من الباركود حساس لحالة الأحرف؟ نعم – يجب أن يتطابق النص تمامًا، بما في ذلك الحالة والمسافات.
ما هو إضافة باركود PDF جافا؟
يشير add barcode pdf java إلى عملية استخدام كود جافا لتضمين باركود (مثل Code128 أو QR أو Data Matrix) داخل ملف PDF. توفر هذه التقنية علامة قابلة للقراءة آليًا يمكن مسحها ضوئيًا أو التحقق منها برمجيًا، مما يتيح تتبعًا سريعًا للمستندات في الأنظمة الداخلية.
لماذا نستخدم توقيعات الباركود بدلاً من التوقيعات الرقمية الكاملة؟
تكون توقيعات الباركود أسرع بنسبة 30‑50 % في الإنشاء والتحقق مقارنةً بالتوقيعات الرقمية القائمة على PKI، وتعمل بشكل موثوق بعد دورة الطباعة‑المسح. كما أنها لا تتطلب إدارة شهادات، مما يجعلها مثالية لسير العمل الداخلي عالي الحجم حيث لا يكون الدليل التشفيري إلزاميًا.
المتطلبات المسبقة
- مجموعة تطوير جافا (JDK) 8+ – يفضَّل Java 11 أو 17 لأداء أفضل.
- بيئة التطوير المتكاملة (IDE) – IntelliJ IDEA أو Eclipse (الأمثلة تستخدم صsyntax IntelliJ).
- أداة البناء – Maven أو Gradle لإدارة الاعتمادات.
إضافة GroupDocs.Signature إلى مشروعك
أسهل طريقة للبدء هي إضافة المكتبة عبر أداة البناء الخاصة بك. إليك الطريقة:
مستخدمي Maven – أضف هذا إلى ملف pom.xml الخاص بك:
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-signature</artifactId>
<version>23.12</version>
</dependency>
مستخدمي Gradle – أضف هذا إلى ملف build.gradle الخاص بك:
implementation 'com.groupdocs:groupdocs-signature:23.12'
تحميل JAR مباشرة – إذا كنت تفضّل الإعداد اليدوي، احصل على ملف JAR من GroupDocs.Signature releases وأضفه إلى مسار الفئة الخاص بك.
ترتيب الترخيص الخاص بك
GroupDocs.Signature ليست مجانية للاستخدام في الإنتاج، ولكن لديك خيارات مرنة:
- تجربة مجانية – حمّل من صفحة تنزيل GroupDocs لاختبار الميزات (يتم إضافة علامات مائية للتقييم).
- ترخيص مؤقت – احصل على وصول كامل لمدة 30 يومًا عبر صفحة الترخيص المؤقت لـ GroupDocs – مثالي لإثبات المفهوم.
- ترخيص كامل – للنشر في بيئات الإنتاج، اطلع على خيارات شراء GroupDocs.
نصيحة احترافية: ابدأ بالترخيص المؤقت للتطوير؛ فهو يزيل العلامات المائية بمجرد التحول إلى مفتاح دائم.
فحص سريع للبيئة
بعد إضافة الاعتماد، شغّل اختبارًا بسيطًا للتأكد من صحة الإعداد:
import com.groupdocs.signature.Signature;
public class SignatureTest {
public static void main(String[] args) {
try {
Signature signature = new Signature("test.pdf");
System.out.println("GroupDocs.Signature initialized successfully!");
signature.dispose();
} catch (Exception e) {
System.err.println("Setup issue: " + e.getMessage());
}
}
}
إذا تم تشغيل البرنامج دون أخطاء، فإن بيئتك جاهزة. إذا واجهت مشاكل، تحقق من نسخة JDK وإصدار المكتبة التي أضفتها.
متى تستخدم توقيعات الباركود
تتفوق توقيعات الباركود في السيناريوهات التالية:
- سير عمل المستندات الداخلي – تتبع الفواتير، أوامر الشراء، أو المذكرات عبر سلاسل الموافقة.
- معالجة عالية الحجم – توقيع آلاف المستندات بسرعة؛ توليد الباركود أسرع حتى 2× من التوقيع الرقمي الكامل.
- جسور الطباعة‑المسح – الباركود يبقى صالحًا بعد دورة الطباعة‑المسح، مما يجعله مثاليًا للعمليات المختلطة بين الورق والرقمية.
- تكامل الأنظمة القديمة – يمكن للماسحات الضوئية للباركود الحالية قراءة العلامات دون الحاجة إلى برامج إضافية.
- سجلات التدقيق – تضمين معرفات المعاملات أو الطوابع الزمنية التي يمكن للمدققين التحقق منها فورًا.
تجنّب استخدام توقيعات الباركود للعقود القانونية، المستندات ذات الأمان العالي، أو تبادل الشركاء الخارجيين حيث تُطلب توقيعات رقمية قائمة على PKI.
إعداد GroupDocs.Signature لجافا
تعريف الفئة الأساسية
فئة Signature هي نقطة الدخول لجميع عمليات التوقيع، والتحقق، والبحث، والتحديث، والحذف في GroupDocs.Signature.
import com.groupdocs.signature.Signature;
التهيئة الأساسية
أنشئ كائن Signature يشير إلى الملف الهدف:
Signature signature = new Signature("path/to/your/document.pdf");
ملاحظات هامة
- يمكن أن تكون المسارات مطلقة أو نسبية؛ استخدم
System.getProperty("user.home")لتوافق عبر الأنظمة. - يدعم GroupDocs أكثر من 30 تنسيقًا للإدخال والإخراج، بما في ذلك PDF وDOCX وXLSX وPPTX وPNG.
- احرص دائمًا على تحرير الموارد باستخدام
signature.dispose()أو كتلة try‑with‑resources:
try (Signature signature = new Signature("path/to/your/document.pdf")) {
// Your signing operations here
} catch (Exception e) {
System.err.println("Error working with document: " + e.getMessage());
}
الآن أنت جاهز لإضافة الباركود.
كيف أضيف باركود إلى ملف PDF في جافا؟
حمّل ملف PDF المصدر باستخدام new Signature("input.pdf")، قم بتكوين كائن BarcodeSignature (مثلاً Code128 بالنص “John Smith”)، واستدعِ sign لإنتاج الملف الموقع – كل ذلك في ثلاث أسطر مختصرة من الكود. يتيح لك هذا النهج تضمين علامة قابلة للقراءة آليًا مع الحفاظ على تخطيط المستند الأصلي، ويعمل مع أي تنسيق مدعوم، ليس فقط PDF.
تنفيذ خطوة بخطوة
1. تعريف مسارات الملفات
حدد مواقع ملفات المصدر والخرج:
String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.docx";
String outputFilePath = "YOUR_OUTPUT_DIRECTORY/signed_sample.docx";
2. إنشاء معالج التوقيع
تهيئة المعالج باستخدام المستند المصدر:
Signature signature = new Signature(filePath);
3. تكوين خيارات الباركود
كائن BarcodeSignature يحدد الخصائص البصرية والبيانات للباركود المراد تضمينه. اضبط نوع الباركود، النص المشفر، الموضع، الحجم، اللون، والخط القابل للقراءة اختياريًا:
BarcodeSignOptions signOptions = new BarcodeSignOptions("John Smith", BarcodeTypes.Code128);
signOptions.setVerticalAlignment(VerticalAlignment.Top);
signOptions.setHorizontalAlignment(HorizontalAlignment.Center);
signOptions.setWidth(100);
signOptions.setHeight(40);
signOptions.setMargin(new java.awt.Rectangle(20, 20, 0, 0));
signOptions.setForeColor(Color.RED);
SignatureFont signatureFont = new SignatureFont();
signatureFont.setSize(12);
signatureFont.setFamilyName("Comic Sans MS");
signOptions.setFont(signatureFont);
نصيحة احترافية: إذا تجاوز النص المشفر 20 حرفًا، قم بزيادة عرض الباركود لتجنب أخطاء المسح.
4. تطبيق التوقيع
نفّذ عملية التوقيع وولد ملف الإخراج:
signature.sign(outputFilePath, signOptions);
5. مثال من الواقع
في نظام موافقة الفواتير قد تقوم بتضمين معرف الموظف للموافق وطابع زمني:
String invoiceId = "INV-2025-0042";
String approver = "john.smith@company.com";
String timestamp = LocalDateTime.now().toString();
// Combine into barcode data
String barcodeData = invoiceId + "|" + approver + "|" + timestamp;
BarcodeSignOptions signOptions = new BarcodeSignOptions(barcodeData, BarcodeTypes.QR);
signOptions.setVerticalAlignment(VerticalAlignment.Bottom);
signOptions.setHorizontalAlignment(HorizontalAlignment.Right);
signature.sign(outputFilePath, signOptions);
الـ PDF الناتج الآن يحمل باركودًا قابلًا للمسح يشفّر جميع بيانات الاعتماد اللازمة للموافقة.
كيف يمكنني التحقق من توقيع باركود في مستند جافا؟
طريقة Signature.verify تتحقق من وجود توقيعات باركود مطابقة في المستند بناءً على الخيارات المقدمة، وتعيد قيمة منطقية تشير إلى ما إذا كان الباركود المتوقع موجودًا. يكون التحقق مفيدًا لسير العمل الآلي حيث تحتاج إلى تأكيد أن المستند قد عُالج من قبل الطرف الصحيح قبل اتخاذ إجراءات أخرى.
خطوات التحقق
1. تحميل المستند الموقع
Signature signature = new Signature("YOUR_OUTPUT_DIRECTORY/signed_sample.docx");
2. تحديد معايير التحقق
حدد النص الدقيق، تنسيق الباركود، ورقم الصفحة التي تتوقعها:
BarcodeVerifyOptions verifyOptions = new BarcodeVerifyOptions();
verifyOptions.setAllPages(false); // Only check the first page
verifyOptions.setPageNumber(1);
verifyOptions.setEncodeType(BarcodeTypes.Code128);
verifyOptions.setText("John Smith");
3. تشغيل التحقق
نفّذ الفحص وتعامل مع النتيجة:
boolean isValid = signature.verify(verifyOptions) != null;
if (isValid) {
System.out.println("Document signature verified successfully!");
} else {
System.out.println("Warning: Signature verification failed!");
}
نمط شائع: لتأكيد وجود أي باركود من نوع معين، احذف مرشح setText:
BarcodeVerifyOptions flexibleOptions = new BarcodeVerifyOptions();
flexibleOptions.setAllPages(true);
flexibleOptions.setEncodeType(BarcodeTypes.Code128);
// No setText() call = accept any text with this barcode type
boolean hasAnySignature = signature.verify(flexibleOptions) != null;
أو تحقق فقط من تنسيق الباركود دون الاهتمام بالمحتوى:
BarcodeVerifyOptions formatOnly = new BarcodeVerifyOptions();
formatOnly.setEncodeType(BarcodeTypes.QR);
// Confirms a QR code exists, regardless of content
تحذير: التحقق حساس لحالة الأحرف والمسافات؛ احرص دائمًا على تقليم وتطبيع البيانات قبل التوقيع.
كيف أبحث عن توقيعات الباركود داخل مستند؟
طريقة Signature.search تفحص المستند بحثًا عن توقيعات باركود تتطابق مع BarcodeSearchOptions المقدمة، وتعيد مجموعة تشمل موقع كل باركود، رقم الصفحة، والقيمة المشفرة. تتيح هذه القدرة استخراج البيانات الضخمة دون فتح كل ملف يدويًا.
سير عمل البحث
1. تهيئة البحث
Signature signature = new Signature("YOUR_OUTPUT_DIRECTORY/signed_sample.docx");
2. تكوين معلمات البحث
حدد نطاق الصفحات، نوع الباركود، أو مرشحات النص:
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(true); // Search the entire document
يمكنك تضييق نطاق البحث اختياريًا لتحسين الأداء:
BarcodeSearchOptions narrowSearch = new BarcodeSearchOptions();
narrowSearch.setAllPages(false);
narrowSearch.setPageNumber(1); // Only search page 1
narrowSearch.setEncodeType(BarcodeTypes.Code128); // Only find Code128 barcodes
3. تنفيذ البحث
java.util.List<BarcodeSignature> signatures = signature.search(BarcodeSignature.class, searchOptions);
System.out.println("Found " + signatures.size() + " barcode signature(s)");
for (BarcodeSignature bcSignature : signatures) {
System.out.println("Barcode Type: " + bcSignature.getEncodeType().getTypeName());
System.out.println("Text: " + bcSignature.getText());
System.out.println("Position: (" + bcSignature.getLeft() + ", " + bcSignature.getTop() + ")");
System.out.println("Size: " + bcSignature.getWidth() + "x" + bcSignature.getHeight());
System.out.println("---");
}
4. مثال على استخراج البيانات
استخراج بيانات الموافقة من كل باركود في دفعة الفواتير:
List<BarcodeSignature> foundSignatures = signature.search(BarcodeSignature.class, searchOptions);
for (BarcodeSignature sig : foundSignatures) {
String barcodeData = sig.getText();
// Parse your custom format (remember our invoice example?)
String[] parts = barcodeData.split("\\|");
if (parts.length == 3) {
String invoiceId = parts[0];
String approver = parts[1];
String timestamp = parts[2];
System.out.println("Invoice " + invoiceId + " approved by " + approver + " at " + timestamp);
}
}
نصيحة أداء: بالنسبة للمستندات التي تتجاوز 100 صفحة، احصر البحث دائمًا على الصفحات التي تحتوي فعليًا على باركود؛ يمكن أن يقلل ذلك من زمن التنفيذ حتى 70 %.
كيف يمكنني تحديث توقيع باركود موجود؟
طريقة Signature.update تعدّل الخصائص البصرية لتوقيع باركود موجود—مثل الموضع، الحجم، أو اللون—مع الحفاظ على البيانات المشفرة الأصلية. هذا مفيد عندما تتطلب تغييرات في التخطيط بعد توقيع المستند.
إجراءات التحديث
1. العثور على التوقيعات للتحديث
Signature signature = new Signature("YOUR_OUTPUT_DIRECTORY/signed_sample.docx");
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(true);
List<BarcodeSignature> signatures = signature.search(BarcodeSignature.class, searchOptions);
2. تعديل الخصائص المطلوبة
List<BarcodeSignature> signaturesToUpdate = new ArrayList<>();
if (!signatures.isEmpty()) {
BarcodeSignature bcSignature = signatures.get(0); // Update the first found signature
// Move it 100px right and 100px down
bcSignature.setLeft(bcSignature.getLeft() + 100);
bcSignature.setTop(bcSignature.getTop() + 100);
// Make it bigger
bcSignature.setWidth(200);
bcSignature.setHeight(50);
signaturesToUpdate.add(bcSignature);
}
يمكنك تغيير عدة خصائص في آن واحد:
bcSignature.setLeft(50);
bcSignature.setTop(50);
bcSignature.setWidth(150);
bcSignature.setHeight(45);
// Note: You can't change the encoded text or barcode type with update
// For that, you'd need to delete and re-sign
3. حفظ التغييرات
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
signature.update(outputStream, signaturesToUpdate);
// If you want to save to a file instead:
// signature.update("path/to/updated_document.docx", signaturesToUpdate);
4. سيناريو من الواقع
إعادة تموضع جميع التوقيعات لتجنب تداخلها مع شعار الشركة المضاف حديثًا:
List<BarcodeSignature> allSignatures = signature.search(BarcodeSignature.class, searchOptions);
List<BarcodeSignature> toUpdate = new ArrayList<>();
for (BarcodeSignature sig : allSignatures) {
// Move all signatures down by 50px to clear space for new logo
if (sig.getTop() < 100) {
sig.setTop(sig.getTop() + 50);
toUpdate.add(sig);
}
}
if (!toUpdate.isEmpty()) {
signature.update(outputStream, toUpdate);
System.out.println("Repositioned " + toUpdate.size() + " signature(s)");
}
قيد: تغيير النص المشفر يتطلب حذف التوقيع وإدخال توقيع جديد.
كيف أحذف توقيعات الباركود من مستند؟
طريقة Signature.delete تحذف بشكل دائم توقيعات الباركود المحددة من المستند، وتزيل العنصر البصري وبياناته المشفرة. استخدم هذه العملية عند تنظيف توقيعات الاختبار أو عندما يصبح الباركود غير ذي صلة.
خطوات الحذف
1. تحديد موقع التوقيعات
Signature signature = new Signature("YOUR_OUTPUT_DIRECTORY/signed_sample.docx");
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(true);
List<BarcodeSignature> signatures = signature.search(BarcodeSignature.class, searchOptions);
2. حذف التوقيعات المحددة
List<BarcodeSignature> signaturesToDelete = new ArrayList<>();
// Delete all Code128 signatures (for example)
for (BarcodeSignature sig : signatures) {
if (sig.getEncodeType().equals(BarcodeTypes.Code128)) {
signaturesToDelete.add(sig);
}
}
if (!signaturesToDelete.isEmpty()) {
boolean result = signature.delete(signaturesToDelete);
if (result) {
System.out.println("Successfully deleted " + signaturesToDelete.size() + " signature(s)");
} else {
System.err.println("Failed to delete signatures");
}
}
3. مثال على الحذف الشرطي
احذف فقط الباركودات الأقدم من طابع زمني محدد (بافتراض أن الطابع الزمني جزء من النص المشفر):
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(30);
List<BarcodeSignature> outdatedSignatures = new ArrayList<>();
for (BarcodeSignature sig : signatures) {
try {
String text = sig.getText();
// Assuming format like "data|timestamp"
String[] parts = text.split("\\|");
if (parts.length > 1) {
LocalDateTime sigDate = LocalDateTime.parse(parts[1]);
if (sigDate.isBefore(cutoffDate)) {
outdatedSignatures.add(sig);
}
}
} catch (Exception e) {
// Skip signatures that don't match our format
continue;
}
}
if (!outdatedSignatures.isEmpty()) {
signature.delete(outdatedSignatures);
System.out.println("Removed " + outdatedSignatures.size() + " outdated signature(s)");
}
تحذير: لا يمكن التراجع عن الحذف؛ احرص دائمًا على العمل على نسخة من ملفات الإنتاج أثناء الاختبار.
4. نمط الحذف الجماعي
نظّف توقيعات الاختبار قبل الإصدار:
// Remove all signatures containing "TEST" in their text
List<BarcodeSignature> testSignatures = signatures.stream()
.filter(sig -> sig.getText().toUpperCase().contains("TEST"))
.collect(Collectors.toList());
if (!testSignatures.isEmpty()) {
signature.delete(testSignatures);
System.out.println("Cleaned up " + testSignatures.size() + " test signature(s)");
}
أنواع الباركود: دليل عملي
اختيار الباركود المناسب يؤثر على موثوقية المسح، سعة البيانات، وتوافق الطابعة.
Code128 (الخيار الأكثر شيوعًا)
- متى يُستخدم: بيانات أبجدية رقمية، كثافة عالية، مستندات مطبوعة.
- الإيجابيات: مدمج، يعمل مع الماسحات القياسية، يطبع بوضوح بأحجام صغيرة.
- السلبيات: يقتصر على ASCII، أقل مقاومة للأخطاء مقارنةً بالرموز الثنائية الأبعاد.
BarcodeSignOptions code128 = new BarcodeSignOptions("INV-2025-042", BarcodeTypes.Code128);
QR Code (الأفضل للهواتف المحمولة)
- متى يُستخدم: مسح الهواتف المحمولة، حمولات بيانات كبيرة (روابط، JSON، إلخ)، مستندات قد تتعرض للتلف.
- الإيجابيات: حتى 4 000 حرف، تصحيح أخطاء مدمج، صديق للهواتف الذكية.
- السلبيات: مساحة بصرية أكبر، يتطلب دقة أعلى للأحجام الصغيرة.
String jsonData = "{\"invoice\":\"INV-042\",\"amount\":1500.00,\"approver\":\"john@company.com\"}";
BarcodeSignOptions qrCode = new BarcodeSignOptions(jsonData, BarcodeTypes.QR);
Code39 (موثوق قديمًا)
- متى يُستخدم: بيئات الماسحات القديمة، الحاجة إلى نص قابل للقراءة البشرية.
- الإيجابيات: دعم واسع للأنظمة القديمة، تنسيق بسيط، لا يتطلب تحقق من المجموع.
- السلبيات: كثافة بيانات منخفضة، مجموعة أحرف محدودة، يشغل مساحة أكبر.
Data Matrix (قوة مدمجة)
- متى يُستخدم: مساحة محدودة للغاية، وضع علامات على عناصر صغيرة، بيانات عالية الكثافة.
- الإيجابيات: مدمج جدًا، تصحيح أخطاء قوي، يعمل على أسطح منحنية.
- السلبيات: يتطلب طباعة عالية الجودة، دعم ماسحات أقل شيوعًا.
مقارنة سريعة
| نوع الباركود | سعة البيانات | الأفضل لـ | الحجم النموذجي |
|---|---|---|---|
| Code128 | ~100 حرف | وسم عام للأغراض | صغير |
| QR Code | ~4 000 حرف | مسح الهواتف المحمولة، بيانات غنية | متوسط |
| Code39 | ~43 حرف | أجهزة قديمة | كبير |
| Data Matrix | ~3 000 حرف | مساحات صغيرة، علامات صناعية | صغير جدًا |
توصية: ابدأ بـ Code128 للمعرفات البسيطة. انتقل إلى QR عندما تحتاج إلى تضمين روابط أو حمولات بيانات أكبر. استخدم Code39 فقط للتكاملات القديمة.
المشكلات الشائعة والحلول
مشكلة: “الباركود غير موجود أثناء التحقق”
الأعراض: التحقق يُعيد false رغم أن الباركود مرئي.
الأسباب الشائعة
- عدم تطابق الحالة (مثال: “John Smith” مقابل “john smith”).
- مسافات إضافية في النص المشفر.
- تحديد نوع باركود غير صحيح في خيارات التحقق.
- البحث في رقم صفحة غير صحيح.
الحل: قم بتطبيع النص قبل التوقيع والتحقق، وتأكد من أن setEncodeType يتطابق مع النوع الأصلي.
// Always normalize your data
String signatureText = originalText.trim().toLowerCase();
// When signing:
BarcodeSignOptions signOptions = new BarcodeSignOptions(signatureText, BarcodeTypes.Code128);
// When verifying:
BarcodeVerifyOptions verifyOptions = new BarcodeVerifyOptions();
verifyOptions.setText(signatureText); // Use the same normalized text
verifyOptions.setEncodeType(BarcodeTypes.Code128);
مشكلة: “الباركود يظهر غير واضح أو غير قابل للقراءة”
الأعراض: لا يمكن مسح الباركود المطبوع.
الأسباب
- أبعاد الباركود صغيرة جدًا بالنسبة للبيانات المشفرة.
- إعدادات طابعة منخفضة الدقة.
- تباين غير كافٍ بين لون الباركود والخلفية.
الحل: زيادة عرض/ارتفاع الباركود، استخدام ألوان ذات تباين عالي (أسود على أبيض)، وضبط DPI الطابعة إلى ما لا يقل عن 300 dpi.
// Increase size for longer strings
int dataLength = barcodeText.length();
int minWidth = Math.max(100, dataLength * 10); // 10px per character minimum
BarcodeSignOptions signOptions = new BarcodeSignOptions(barcodeText, BarcodeTypes.Code128);
signOptions.setWidth(minWidth);
signOptions.setHeight(60); // Taller = easier to scan
// Use high-contrast colors
signOptions.setForeColor(Color.BLACK); // Black on white is most reliable
signOptions.setBackColor(Color.WHITE);
مشكلة: “OutOfMemoryError مع مستندات كبيرة”
الأعراض: تعطل التطبيق عند معالجة ملفات PDF بمئات الصفحات.
السبب: المكتبة تحمل المستند بالكامل في الذاكرة.
الحل: تمكين وضع البث ومعالجة الصفحات تدريجيًا.
// Process pages in batches instead of all at once
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(false);
List<BarcodeSignature> allSignatures = new ArrayList<>();
for (int page = 1; page <= totalPages; page++) {
searchOptions.setPageNumber(page);
List<BarcodeSignature> pageSignatures = signature.search(BarcodeSignature.class, searchOptions);
allSignatures.addAll(pageSignatures);
// Process and clear as you go
if (page % 10 == 0) {
System.gc(); // Suggest garbage collection every 10 pages
}
}
مشكلة: “موضع التوقيع غير متسق عبر أنواع المستندات”
الأعراض: تظهر الباركودات في مواقع مختلفة عند توقيع PDF مقابل مستندات Word.
السبب: يستخدم PDF أصلًا من أسفل اليسار، بينما يستخدم Word أصلًا من أعلى اليسار.
الحل: اكتشف نوع المستند وطبق التحويل المناسب للإحداثيات.
// Use relative positioning instead of absolute
signOptions.setVerticalAlignment(VerticalAlignment.Bottom);
signOptions.setHorizontalAlignment(HorizontalAlignment.Right);
// Then use margins for fine-tuning
Padding margin = new Padding();
margin.setRight(50); // 50px from right edge
margin.setBottom(50); // 50px from bottom
signOptions.setMargin(margin);
// This works consistently across PDF, DOCX, XLSX, etc.
مشكلة: “التوقيعات المحدثة تفقد التنسيق”
الأعراض: بعد استدعاء update، يتغير لون أو خط الباركود بشكل غير متوقع.
السبب: لا يتم حفظ جميع الخصائص البصرية أثناء عملية التحديث.
الحل: أعد تطبيق أي إعدادات بصرية بعد استدعاء التحديث.
// When updating, explicitly set all visual properties
bcSignature.setLeft(newLeft);
bcSignature.setTop(newTop);
bcSignature.setWidth(originalWidth); // Don't forget these!
bcSignature.setHeight(originalHeight);
// Note: Color and font can't be updated - you'd need to delete and re-sign
أفضل الممارسات للإنتاج
تحسين الأداء
- إعادة استخدام كائنات Signature – أنشئ كائن
Signatureواحد لكل مستند وأعد استخدامه للعمليات المتعددة.
// Bad - Creates new instance each time
public void processDocument(String path) {
Signature sig1 = new Signature(path);
sig1.search(/* ... */);
Signature sig2 = new Signature(path); // Unnecessary reload
sig2.verify(/* ... */);
}
// Good - Reuse the same instance
public void processDocument(String path) {
try (Signature signature = new Signature(path)) {
signature.search(/* ... */);
signature.verify(/* ... */);
signature.update(/* ... */);
}
}
- البحث في صفحات محددة فقط – حدّد نطاق الصفحات إلى تلك التي يُتوقع وجود الباركود فيها.
// Slow for 100+ page documents
BarcodeSearchOptions slowSearch = new BarcodeSearchOptions();
slowSearch.setAllPages(true);
// Fast - only check where signatures actually are
BarcodeSearchOptions fastSearch = new BarcodeSearchOptions();
fastSearch.setAllPages(false);
fastSearch.setPageNumber(1); // Only check cover page
- اختر أبسط نوع باركود – الباركود البسيط يولد أسرع؛ استخدم QR أو Data Matrix فقط عندما تحتاج فعلاً إلى سعة إضافية.
// Overkill for simple IDs
BarcodeSignOptions slow = new BarcodeSignOptions("12345", BarcodeTypes.QR);
// Faster and more appropriate
BarcodeSignOptions fast = new BarcodeSignOptions("12345", BarcodeTypes.Code128);
اعتبارات الأمان
- لا تقم بترميز بيانات شخصية حساسة – الباركود سهل القراءة؛ تجنّب البيانات الشخصية مثل أرقام الضمان الاجتماعي أو كلمات المرور.
// Bad - exposes sensitive data
String barcodeData = "SSN:123-45-6789|Password:hunter2";
// Good - use reference IDs
String barcodeData = "USER-REF-7721X"; // Look up sensitive data server-side
- التحقق من الجانب الخادمي – لا تثق أبدًا في التحقق من جانب العميل فقط؛ دائمًا أعد التحقق على خادم موثوق.
// Client scans barcode and extracts "APPROVED-BY-ADMIN"
// Always verify server-side:
public boolean verifyApproval(String documentId, String scannedData) {
// Load document from secure storage
Signature signature = new Signature(getSecureDocument(documentId));
BarcodeVerifyOptions verifyOptions = new BarcodeVerifyOptions();
verifyOptions.setText(scannedData);
boolean isValid = signature.verify(verifyOptions) != null;
// Also check against your database
boolean isInDatabase = checkApprovalDatabase(documentId, scannedData);
return isValid && isInDatabase;
}
- إضافة طوابع زمنية – تضمّن طابعًا زمنيًا في حمولة الباركود لمنع هجمات إعادة التشغيل.
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
String timestamp = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS).toString();
String barcodeData = "APPROVAL|" + userId + "|" + timestamp;
// When verifying, check the timestamp isn't too old
public boolean isSignatureRecent(String barcodeData, int maxAgeHours) {
String[] parts = barcodeData.split("\\|");
if (parts.length < 3) return false;
LocalDateTime signatureTime = LocalDateTime.parse(parts[2]);
LocalDateTime now = LocalDateTime.now();
long hoursSince = ChronoUnit.HOURS.between(signatureTime, now);
return hoursSince <= maxAgeHours;
}
أنماط معالجة الأخطاء
- استخدم دائمًا Try‑With‑Resources لضمان تحرير كائنات
Signature.
try (Signature signature = new Signature(documentPath)) {
// Your operations here
signature.sign(outputPath, signOptions);
} catch (Exception e) {
logger.error("Failed to sign document: " + documentPath, e);
throw new DocumentSigningException("Could not process document", e);
}
- تحقق من صلاحية الوصول إلى الملف قبل محاولة التوقيع.
public void signDocument(String inputPath, String outputPath) {
File inputFile = new File(inputPath);
if (!inputFile.exists()) {
throw new IllegalArgumentException("Input file not found: " + inputPath);
}
if (!inputFile.canRead()) {
throw new SecurityException("Cannot read input file: " + inputPath);
}
File outputDir = new File(outputPath).getParentFile();
if (outputDir != null && !outputDir.exists()) {
outputDir.mkdirs();
}
try (Signature signature = new Signature(inputPath)) {
signature.sign(outputPath, signOptions);
}
}
- مزامنة الوصول إذا كان من الممكن أن تعمل عدة خيوط على نفس الملف.
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.ConcurrentHashMap;
public class SignatureManager {
private final ConcurrentHashMap<String, ReentrantLock> documentLocks = new ConcurrentHashMap<>();
public void signDocument(String documentPath, BarcodeSignOptions options) {
ReentrantLock lock = documentLocks.computeIfAbsent(documentPath, k -> new ReentrantLock());
lock.lock();
try (Signature signature = new Signature(documentPath)) {
signature.sign(documentPath + ".signed", options);
} finally {
lock.unlock();
}
}
}
اختبار تنفيذك
قالب اختبار الوحدة
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import static org.junit.jupiter.api.Assertions.*;
public class BarcodeSignatureTest {
@TempDir
Path tempDir;
@Test
public void testSignAndVerify() throws Exception {
// Setup
String testDoc = "test-document.pdf";
String outputDoc = tempDir.resolve("signed-test.pdf").toString();
String testData = "TEST-USER-12345";
// Sign
try (Signature signature = new Signature(testDoc)) {
BarcodeSignOptions signOptions = new BarcodeSignOptions(testData, BarcodeTypes.Code128);
signature.sign(outputDoc, signOptions);
}
// Verify
try (Signature signature = new Signature(outputDoc)) {
BarcodeVerifyOptions verifyOptions = new BarcodeVerifyOptions();
verifyOptions.setText(testData);
verifyOptions.setEncodeType(BarcodeTypes.Code128);
boolean isValid = signature.verify(verifyOptions) != null;
assertTrue(isValid, "Signature should be valid");
}
}
@Test
public void testSearchFindsSignature() throws Exception {
String signedDoc = "signed-document.pdf";
try (Signature signature = new Signature(signedDoc)) {
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(true);
List<BarcodeSignature> signatures = signature.search(BarcodeSignature.class, searchOptions);
assertFalse(signatures.isEmpty(), "Should find at least one signature");
assertEquals("TEST-USER-12345", signatures.get(0).getText());
}
}
}
قائمة التحقق للتكامل
- ✅ اختبار جميع الصيغ المدعومة (PDF, DOCX, XLSX, PPTX, PNG).
- ✅ التحقق من بقاء الباركودات صالحة بعد دورة الطباعة‑المسح.
- ✅ اختبار الضغط بأطول سلاسل البيانات.
- ✅ تأكيد التموقع على أحجام الصفحات A4، Letter، والصفحات المخصصة.
- ✅ تشغيل توقيع متزامن على مستندات متعددة.
- ✅ مراقبة استهلاك الذاكرة للمستندات التي تزيد عن 500 صفحة.
- ✅ التأكد من أن ماسحات الباركود تقرأ المخرجات بشكل موثوق.
التسجيل والمراقبة
أضف سجلات ذات معنى حول كل عملية:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DocumentSigningService {
private static final Logger logger = LoggerFactory.getLogger(DocumentSigningService.class);
public void signDocument(String docPath, String barcodeData) {
logger.info("Starting signature process for document: {}", docPath);
logger.debug("Barcode data length: {} characters", barcodeData.length());
try (Signature signature = new Signature(docPath)) {
BarcodeSignOptions options = new BarcodeSignOptions(barcodeData, BarcodeTypes.Code128);
long startTime = System.currentTimeMillis();
signature.sign(docPath + ".signed", options);
long duration = System.currentTimeMillis() - startTime;
logger.info("Successfully signed document in {}ms", duration);
} catch (Exception e) {
logger.error("Failed to sign document: {}", docPath, e);
throw new RuntimeException("Signature operation failed", e);
}
}
}
تتبع المقاييس الرئيسية مثل زمن المعالجة، استهلاك الذاكرة، ومعدلات الأخطاء:
// Track success/failure rates
metricsService.incrementCounter("signature.sign.success");
metricsService.incrementCounter("signature.verify.failure");
// Track performance
metricsService.recordTimer("signature.sign.duration", duration);
// Track document sizes
metricsService.recordHistogram("signature.document.pages", pageCount);
نصائح احترافية من الاستخدام الفعلي
استراتيجية المعالجة الدفعية عند التعامل مع مئات الملفات، عالجها على دفعات وقدم تقارير عن التقدم:
public void signBatch(List<String> documents, String barcodePrefix) {
int total = documents.size();
int completed = 0;
int failed = 0;
for (String docPath : documents) {
try {
String barcodeData = barcodePrefix + "-" + UUID.randomUUID().toString();
signDocument(docPath, barcodeData);
completed++;
if (completed % 10 == 0) {
logger.info("Progress: {}/{} documents signed", completed, total);
}
} catch (Exception e) {
failed++;
logger.warn("Failed to sign: {}", docPath, e);
}
}
logger.info("Batch complete: {} succeeded, {} failed", completed, failed);
}
خارجية التكوين احفظ إعدادات الباركود (النوع، الحجم، اللون) في ملف خصائص لتعديل سهل دون إعادة تجميع.
public class BarcodeConfig {
private int defaultWidth = 100;
private int defaultHeight = 40;
private String defaultBarcodeType = "Code128";
private String defaultColor = "BLACK";
// Load from properties file or environment variables
public BarcodeConfig() {
this.defaultWidth = Integer.parseInt(
System.getProperty("barcode.width", "100")
);
// ... load other properties
}
public BarcodeSignOptions createDefaultOptions(String text) {
BarcodeSignOptions options = new BarcodeSignOptions(text, getBarcodeType());
options.setWidth(defaultWidth);
options.setHeight(defaultHeight);
options.setForeColor(getColor());
return options;
}
}
توحيد حمولة الباركود
استخدم تنسيقًا مفصولًا مثل EMPID|TIMESTAMP|DOCID لجعل التحليل بسيطًا ومتسقًا.
public class BarcodeDataBuilder {
private String userId;
private String action;
private LocalDateTime timestamp;
private String documentId;
public BarcodeDataBuilder setUserId(String userId) {
this.userId = userId;
return this;
}
public BarcodeDataBuilder setAction(String action) {
this.action = action;
return this;
}
public BarcodeDataBuilder setDocumentId(String documentId) {
this.documentId = documentId;
return this;
}
public String build() {
this.timestamp = LocalDateTime.now();
// Format: VERSION|USER|ACTION|DOC_ID|TIMESTAMP|CHECKSUM
String data = String.join("|",
"v1",
userId,
action,
documentId,
timestamp.toString()
);
// Add simple checksum
int checksum = data.hashCode();
return data + "|" + checksum;
}
public static ParsedBarcodeData parse(String barcodeData) {
String[] parts = barcodeData.split("\\|");
if (parts.length != 6 || !parts[0].equals("v1")) {
throw new IllegalArgumentException("Invalid barcode format");
}
return new ParsedBarcodeData(parts[1], parts[2], parts[3],
LocalDateTime.parse(parts[4]));
}
}
// Usage:
String barcodeData = new BarcodeDataBuilder()
.setUserId("john.smith")
.setAction("APPROVED")
.setDocumentId("INV-2025-042")
.build();
اكتشاف نوع المستند تلقائيًا اضبط أبعاد الباركود بناءً على ما إذا كان الهدف PDF أو Word أو صورة.
public BarcodeSignOptions getOptimalOptions(String documentPath, String text) {
String extension = documentPath.substring(documentPath.lastIndexOf(".") + 1).toLowerCase();
BarcodeSignOptions options = new BarcodeSignOptions(text, BarcodeTypes.Code128);
switch (extension) {
case "pdf":
// PDFs can handle larger, detailed barcodes
options.setWidth(150);
options.setHeight(50);
break;
case "docx":
case "doc":
// Word docs need compact signatures that don't disrupt flow
options.setWidth(100);
options.setHeight(35);
options.setVerticalAlignment(VerticalAlignment.Bottom);
break;
case "xlsx":
case "xls":
// Excel needs signatures that don't obscure data
options.setWidth(80);
options.setHeight(30);
options.setHorizontalAlignment(HorizontalAlignment.Right);
break;
default:
// Safe defaults
options.setWidth(100);
options.setHeight(40);
}
return options;
}
موارد إضافية
- GroupDocs.Signature documentation – دليل API كامل وأمثلة الاستخدام.
- GroupDocs support forum – مساعدة المجتمع وحل المشكلات.
- API reference – توقيعات الطرق التفصيلية ووصف المعلمات.
الأسئلة المتكررة
س: هل يمكنني استخدام GroupDocs.Signature مع Java 17؟
ج: نعم – المكتبة متوافقة بالكامل مع JDK 8 و 11 و 17.
س: هل يبقى الباركود صالحًا بعد دورة الطباعة‑المسح؟
ج: عند استخدام Code128 أو QR بحجم وتباين كافيين، يظل الباركود قابلًا للمسح بعد الطباعة والمسح.
س: كم عدد الباركودات التي يمكن أن يحتويها مستند واحد؟
ج: لا يوجد حد ثابت؛ ومع ذلك، للحصول على أداء مثالي حافظ على عددها الإجمالي أقل من 200 لكل مستند.
س: هل يلزم ترخيص لبنات التطوير؟
ج: الترخيص المؤقت يزيل العلامات المائية للتقييم؛ الترخيص الكامل إلزامي لأي نشر إنتاجي.
س: هل يمكنني توقيع ملفات PDF محمية بكلمة مرور؟
ج: نعم – قدم كلمة المرور عند إنشاء كائن Signature؛ سيقوم API بفتح الملف داخليًا.
آخر تحديث: 2026-07-15
تم الاختبار مع: GroupDocs.Signature 23.9 لجافا
المؤلف: GroupDocs