تحويل مستندات Office إلى PDF باستخدام Gotenberg
نظرة سريعة
قسم بعنوان «نظرة سريعة»يحوِّل جسر Gotenberg مستند Office إلى PDF. يرسل المستند إلى خدمة Gotenberg المصغَّرة عبر HTTPS ويعيد بايتات PDF. عرِّف الخدمة عبر GotenbergConfig غير قابل للتغيير، وصِل عميل PSR-18 ومصانع PSR-17 بـGotenbergBridge، وافحص سلامة الخدمة، ثم حوِّل ملفًا من القرص أو بايتات في الذاكرة. يغطي هذا الدليل اكتشاف التنسيق المعتمد على الامتداد، ومسبار السلامة، وعقد الإخفاق المصنَّف، والتسليم إلى المعالجة اللاحقة في NextPDF.
المتطلبات الأساسية موضحة من البداية:
- نواة NextPDF و
nextpdf/gotenbergمثبَّتان. - خدمة Gotenberg يمكن الوصول إليها عبر HTTPS. يرفض الجسر عنوان
http://العادي قبل أن تغادر أي طلب العملية. - عميل PSR-18 ومصنعا الطلب والدفق من PSR-17 مثبَّتون. لتثبيت DNS وTLS، تزوِّد أيضًا مصنع استجابة من PSR-17.
- يجب أن يكون الإدخال أحد تنسيقات Office الستة المعترف بها:
.docx،.xlsx،.pptx،.odt،.ods، أو.odp. يرفض الجسر أي امتداد آخر معValueError.
هذا دليل إرشادي عملي. للاطلاع على برنامج كامل وقابل للتشغيل، اقرأ دليل البدء السريع لـ Gotenberg.
التثبيت
قسم بعنوان «التثبيت»ثبِّت الجسر وعميل PSR-18 ومصانع PSR-17.
composer require nextpdf/gotenberg guzzlehttp/guzzleشغِّل خدمة Gotenberg يمكن الوصول إليها عبر HTTPS. احصل على أي رمز حامل من مدير أسرار أو من قيمة بيئة محقونة. لا يقرأ الجسر متغيرات البيئة أبدًا ولا ينشئ عميل HTTP أبدًا؛ فأنت من يزوِّد كليهما.
نظرة مفاهيمية عامة
قسم بعنوان «نظرة مفاهيمية عامة»يأخذ GotenbergBridge::convertFile() مسارًا على القرص. يحوِّل المسار إلى صورته المعيارية لمنع الاجتياز، ويربط امتداد الملف بتنسيق مدعوم، ويفحص الحجم واسم الملف، ويرسل طلبًا متعدد الأجزاء إلى <apiUrl>/forms/libreoffice/convert. يتبع convertString() المسار نفسه للبايتات التي تملكها بالفعل، ويستخدم اسم الملف الأصلي حتى يمكن اكتشاف الامتداد.
يعتمد اكتشاف التنسيق على الامتداد. يربط الجسر .docx، .xlsx، .pptx، .odt، .ods، و.odp بتنسيقاتها ويرفض أي شيء آخر مع ValueError قبل أي حركة مرور على الشبكة. يكشف كائن النتيجة تنسيق المصدر المكتشَف كقيمة تعداد.
يجري الجسر رحلة HTTP متزامنة واحدة ذهابًا وإيابًا، محاطة بالتحقق. لا يعيد المحاولة، ولا يضع في قائمة انتظار، ولا يخزن مؤقتًا، ولا يحدد معدل الطلبات؛ فهذه الضوابط تنتمي إلى التطبيق المحيط بالجسر. تعامَل مع كل تحويل بوصفه استدعاءً بعيدًا إلى خدمة تشغِّلها لكنك لا تتحكم فيها داخل العملية، وصمِّم لزمن استجابتها وأنماط إخفاقها.
يبلِّغ الجسر عن الإخفاقات كاستثناءات مصنَّفة، ولا يعيد أبدًا نتيجة جزئية أو غير متحقَّق منها:
- حالة غير
200، أوContent-Typeبدونapplication/pdf، أو متن لا يبدأ بـ%PDFيثيرGotenbergConvertException. يعيد الجسر نتيجة فقط عندما تجتاز الفحوص الثلاثة جميعها. - إخفاق عميل PSR-18، بما في ذلك إخفاق الشبكة أو انتهاء المهلة، يُغلَّف بوصفه
GotenbergConvertExceptionمع الاستثناء الأصلي بوصفه السبب. - إخفاقات التحقق (عنوان غير HTTPS، عنوان خاص أو محجوز، إدخال مفرط الحجم، اسم ملف غير آمن) تثير
RuntimeExceptionقبل أي حركة مرور على الشبكة. - امتداد ملف غير معترف به يثير
ValueErrorقبل أي حركة مرور على الشبكة.
واجهة برمجة التطبيقات
قسم بعنوان «واجهة برمجة التطبيقات»// Configuration (final readonly):new GotenbergConfig( string $apiUrl, // required, must be HTTPS int $timeout = 30, // hard transfer timeout, seconds int $maxFileSize = 52_428_800, // 50 MiB string $apiKey = '', // #[SensitiveParameter]; Bearer when non-empty list<string> $pinnedPublicKeys = [], // sha256/<base64> list<string> $backupPublicKeys = [],)GotenbergConfig::fromArray(array $config): selfGotenbergConfig::isValid(): bool
// The bridge:new GotenbergBridge( GotenbergConfig $config, ClientInterface $httpClient, // PSR-18 RequestFactoryInterface $requestFactory, // PSR-17 StreamFactoryInterface $streamFactory, // PSR-17 ?LoggerInterface $logger = null, // PSR-3 ?HtmlSecurityPolicyInterface $htmlSecurityPolicy = null, ?ResponseFactoryInterface $responseFactory = null, // enables pinned transport)GotenbergBridge::isAvailable(): boolGotenbergBridge::convertFile(string $path): GotenbergConvertResultGotenbergBridge::convertString(string $bytes, string $originalFilename): GotenbergConvertResultيكشف كائن النتيجة pdfData، وتعداد sourceFormat، وisValid() (صحيح عندما يكون المتن غير فارغ ويبدأ بـ%PDF)، وsize(). للاطلاع على المرجع الكامل للحقول، وخريطة مفاتيح fromArray()، وقواعد اختيار النقل، راجع صفحة إعدادات Gotenberg المرتبطة ضمن طالِع أيضًا.
عيِّنة شيفرة — البدء السريع
قسم بعنوان «عيِّنة شيفرة — البدء السريع»عرِّف الخدمة، وصِل الجسر، وافحص جاهزيته، وحوِّل ملفًا واحدًا.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Gotenberg\GotenbergBridge;use NextPDF\Gotenberg\GotenbergConfig;use NextPDF\Gotenberg\GotenbergConvertException;
$config = new GotenbergConfig( apiUrl: 'https://gotenberg.example.com', timeout: 60, apiKey: getenv('GOTENBERG_TOKEN') ?: '',);
$bridge = new GotenbergBridge( config: $config, httpClient: $httpClient, // your PSR-18 client requestFactory: $requestFactory, // your PSR-17 factory streamFactory: $streamFactory, // your PSR-17 factory responseFactory: $responseFactory, // enables the pinned transport);
// Probe before converting. The probe validates the URL with no network// traffic, then sends a HEAD to <apiUrl>/health.if (!$bridge->isAvailable()) { throw new RuntimeException('Gotenberg is not reachable.');}
try { $result = $bridge->convertFile('/path/to/report.docx');} catch (GotenbergConvertException $exception) { // Bad config, HTTP failure, non-200, wrong Content-Type, or non-PDF body. throw $exception;}
if (!$result->isValid()) { throw new RuntimeException('Result is not a valid PDF.');}
file_put_contents('/path/to/report.pdf', $result->pdfData);الفئة هي NextPDF\Gotenberg\GotenbergConfig (يستخدم السطر أعلاه مساحة الاسم الدقيقة التي يجب أن تستوردها شيفرتك). يعيد isAvailable() القيمة false ولا يثير استثناءً أبدًا لعنوان فارغ أو غير HTTPS أو عنوان خاص، أو لأي خطأ في الشبكة؛ فحالة أقل من 500 من /health تعني أنها متاحة.
عيِّنة شيفرة — الإنتاج
قسم بعنوان «عيِّنة شيفرة — الإنتاج»يلتقط تحويل الإنتاج كل نوع إخفاق على حدة، ويعيد المحاولة فقط عندما تكون الظروف ملائمة، ويحدّ التزامن في جانب المستدعي. ترتيب الالتقاط أدناه شامل وحصري.
<?php
declare(strict_types=1);
use NextPDF\Gotenberg\GotenbergBridge;use NextPDF\Gotenberg\GotenbergConvertException;use Psr\Log\LoggerInterface;use RuntimeException;use ValueError;
final readonly class OfficeConverter{ public function __construct( private GotenbergBridge $bridge, private LoggerInterface $logger, ) {}
public function convert(string $path): string { try { $result = $this->bridge->convertFile($path); } catch (GotenbergConvertException $exception) { // Transport, non-200, wrong Content-Type, or non-PDF body. // Retry only on transport-level or 502/503/504 causes, with // bounded exponential backoff and jitter — never blind retries. $this->logger->error('gotenberg.convert.failed', [ 'path' => basename($path), 'exception' => $exception::class, ]); throw $exception; } catch (ValueError $exception) { // Extension is not one of the six recognized Office formats. $this->logger->warning('gotenberg.convert.unsupported_format', [ 'path' => basename($path), ]); throw $exception; } catch (RuntimeException $exception) { // Non-HTTPS URL, private address, oversized input, or unsafe name. $this->logger->error('gotenberg.convert.rejected', [ 'path' => basename($path), 'exception' => $exception::class, ]); throw $exception; }
if (!$result->isValid()) { throw new RuntimeException('Gotenberg returned an invalid PDF body.'); }
return $result->pdfData; }}أعِد المحاولة فقط عند GotenbergConvertException على مستوى النقل (استثناء عميل PSR-18 مغلَّف) وعند أخطاء الخادم التي لا تخلّف أثرًا (502، 503، 504). تعني استجابة من فئة 400 عادةً أن الإدخال خاطئ، لذا ستفشل إعادة المحاولة بالطريقة نفسها. حدِّد إجمالي المحاولات وزمن التنفيذ الفعلي الإجمالي. حدِّد عدد التحويلات الجارية بما يتناسب مع السعة التي يتحملها نشر Gotenberg لديك. الجسر نفسه عديم الحالة وآمن للاستخدام من عمَّال كثيرين، لكن للخدمة سعة تحويل محدودة.
الحالات الحدية والمزالق
قسم بعنوان «الحالات الحدية والمزالق»- اكتشاف التنسيق يكون بالامتداد.
.docxأُعيدت تسميته إلى.txtيُرفض معValueError؛ و.txtأُعيدت تسميته إلى.docxيُرسَل إلى Gotenberg ويفشل هناك. عند قبول عمليات الرفع، اعتمد على التنسيق الحقيقي، لا على الاسم. fromArray()متسامح بحكم التصميم. يستبدل القيم الافتراضية بصمت للإدخال المشوَّه. تحقَّق من مصفوفة المصدر في مسار بدء التشغيل لديك حتى يظهر العنوان المفقود مبكرًا كخطأ في الإعداد، لا كاستثناء في كل تحويل.- حدّ الحجم مُطبَّق داخل العملية.
maxFileSize(الافتراضي 50 MiB) يُفحَص قبل إرسال الطلب، حتى لا يستهلك ملف مفرط الحجم سعة الخدمة أبدًا. اخفض الحدّ ليطابق ما تحتاجه مستنداتك؛ فالحدّ الأصغر ضابط أرخص ضد حجب الخدمة. - المسبار ليس مجانيًا. استدعِ
isAvailable()من نقطة نهاية الجاهزية أو السلامة، لا قبل كل تحويل. تشغيله مع كل تحويل يضاعف معدل طلباتك على الخدمة دون أي فائدة. - لا يوجد تخزين مؤقت داخل العملية. إذا جرى تحويل المستند نفسه تكرارًا، فخزِّن PDF الناتج مؤقتًا في تطبيقك، مفهرسًا بتجزئة محتوى الإدخال.
renderTimeMsتضبطه أنت. حقل التوقيت في النتيجة هو0.0ما لم يَقِسه تكاملك ويضبطه. قِس الاستدعاء بنفسك إن احتجت إلى الرقم.
الأداء
قسم بعنوان «الأداء»طوال مدة الطلب، يحتجز التحويل اتصالًا واحدًا وعاملًا واحدًا من LibreOffice على جانب Gotenberg، وتحويل Office يستغرق وقتًا. اضبط timeout بناءً على زمن استجابة التحويل المقاس لمستنداتك الحقيقية، مع هامش مناسب. اجعله أقل من مهلة أي بوابة وسيطة أعلى أو من max_execution_time الخاص بـ PHP، حتى تنتهي مهلة الجسر أولًا فتحصل على استثناء مصنَّف بدلًا من عملية منتهية قسرًا. حدِّد التزامن بقائمة انتظار أو سيمافور أو مجمَّع عمَّال بحجم يناسب سعة الخدمة. لا يوجد تخزين مؤقت داخل العملية؛ أضِف واحدًا في تطبيقك إذا حوَّلت الإدخال نفسه تكرارًا.
ملاحظات أمنية
قسم بعنوان «ملاحظات أمنية»- HTTPS وفحص العنوان قبل الإرسال. يرفض الجسر عنوانًا غير HTTPS ووجهة تُحَل إلى مساحة عناوين خاصة أو محجوزة قبل أن يغادر أي طلب العملية. كل استدعاء يُعاد المحاولة يعيد تشغيل ذلك التحقق، لذا لا يمكن لإعادة المحاولة تجاوز ضابط SSRF.
- النقل المثبَّت عند الطلب. عندما تزوِّد مصنع استجابة وتثبيتات (أو عندما توجد مجموعة IP محلَّلة)، يربط الجسر الاتصال بالعناوين المحلَّلة، ويفرض تثبيت SPKI، ويتحقق من النظير والمضيف، ويطبِّق المهلة، ويعطِّل اتباع إعادة التوجيه. جهِّز تثبيتًا احتياطيًا قبل تدوير الشهادة.
- لا تثق بنوع المحتوى المعلَن لعملية رفع. عند قبول عمليات رفع المستخدمين، تحقَّق من نوع الملف الحقيقي بنفسك؛ فخريطة الامتداد إلى التنسيق قرار توجيه، لا فحص أصالة.
- الأسرار محجوبة وغير قابلة للتغيير.
apiKeyيحمل#[SensitiveParameter]، والإعدادfinal readonly. احصل على الرمز من مدير أسرار؛ لا تودِعه في المستودع أبدًا. يتضمن سجل التحويل عند تدوينه العنوان واسم الملف والتنسيق وطول المحتوى — لا محتويات الملف ولا الرمز أبدًا. - لا تكتب أبدًا كتلة
catchفارغة. كل مثال يلتقط النوع المحدَّد ويدوِّن مع السياق.
للاطلاع على نموذج الأمان والنشر الكامل، راجع صفحة أمان وعمليات Gotenberg. عقد نقل PSR-18 وإرشاد عدم الوثوق بنوع المحتوى مرتبطان ببنودهما في صفحة استخدام الإنتاج الأعلى.
المطابقة
قسم بعنوان «المطابقة»لا يقدِّم هذا الدليل بحد ذاته أي ادعاء معياري. سلوك نقل PSR-18 للجسر (لا يثير العميل استثناءً إلا عندما يتعذَّر عليه إرسال استجابة أو تحليلها؛ و4xx/5xx قيمة إرجاع عادية)، وإرشاد التحقق من رفع الملفات، ونموذج تثبيت TLS، مثبتة إلى PSR-18 وOWASP وRFC 7469 في صفحتَي استخدام الإنتاج والإعداد الأعلى لـ Gotenberg. تعيد صفحة دليل الطبخ هذه ذكر الاستخدام وتؤجِّل تلك الاستشهادات إلى تلك الصفحات. ينتج الجسر بايتات PDF ويتوقف. التوقيع، وملفات تعريف PDF/A، ووضع العلامات المائية، شؤون معالجة NextPDF اللاحقة وإمكانات في الإصدار التجاري، وليست جزءًا من هذا الجسر.
طالِع أيضًا
قسم بعنوان «طالِع أيضًا»- إرجاع PDF مُولَّد من وحدة تحكم — إرجاع PDF مُحوَّل كاستجابة HTTP.
- دليل البدء السريع لـ Gotenberg — برنامج التحويل الكامل القابل للتشغيل.
- إعدادات Gotenberg — كل حقل، وخريطة
fromArray()، واختيار النقل. - استخدام Gotenberg في الإنتاج — الأسرار، والمهلات، وإعادة المحاولات، والتزامن، وحدّ معالجة ما بعد التحويل.