แปลงเอกสาร Office เป็น PDF ด้วย Gotenberg
ภาพรวมโดยสังเขป
หัวข้อที่มีชื่อว่า “ภาพรวมโดยสังเขป”Gotenberg bridge แปลงเอกสาร Office เป็น PDF โดยส่งเอกสารไปยังไมโครเซอร์วิส Gotenberg ผ่าน HTTPS แล้วคืนค่าเป็นไบต์ของ PDF คุณอธิบายบริการด้วย GotenbergConfig แบบไม่เปลี่ยนแปลงค่าได้ เชื่อมไคลเอนต์แบบ PSR-18 และแฟกทอรีแบบ PSR-17 เข้ากับ GotenbergBridge ตรวจสุขภาพบริการ และแปลงไฟล์จากดิสก์หรือจากไบต์ในหน่วยความจำ คู่มือนี้ครอบคลุมการตรวจหารูปแบบจากนามสกุลไฟล์ การโพรบสุขภาพ สัญญาความล้มเหลวแบบมีชนิด และการส่งต่อไปยังการประมวลผลภายหลังของ NextPDF
ข้อกำหนดเบื้องต้นมีดังนี้:
- ติดตั้งแกนหลักของ NextPDF และ
nextpdf/gotenbergแล้ว - บริการ Gotenberg เข้าถึงได้ผ่าน HTTPS bridge จะปฏิเสธ URL แบบ
http://ธรรมดาก่อนส่งคำขอใดๆ ออกจากกระบวนการ - ติดตั้งไคลเอนต์แบบ PSR-18 และแฟกทอรีสำหรับคำขอและสตรีมแบบ PSR-17 แล้ว หากใช้การปักหมุด DNS และ TLS คุณยังต้องจัดเตรียมแฟกทอรีสำหรับการตอบกลับแบบ PSR-17 ด้วย
- อินพุตเป็นหนึ่งในหกรูปแบบ Office ที่รองรับ:
.docx,.xlsx,.pptx,.odt,.odsหรือ.odpโดย bridge จะปฏิเสธนามสกุลอื่นใดด้วยValueError
เอกสารนี้เป็นคู่มือเชิงปฏิบัติ (how-to) สำหรับโปรแกรมที่สมบูรณ์และเรียกใช้ได้ โปรดอ่าน Gotenberg quickstart
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”ติดตั้ง bridge พร้อมไคลเอนต์แบบ PSR-18 และแฟกทอรีแบบ PSR-17
composer require nextpdf/gotenberg guzzlehttp/guzzleรันบริการ Gotenberg ที่เข้าถึงได้ผ่าน HTTPS ดึง bearer token จากตัวจัดการความลับหรือจากค่าสภาพแวดล้อมที่ฉีดเข้ามา bridge จะไม่อ่านตัวแปรสภาพแวดล้อมและจะไม่สร้างไคลเอนต์ HTTP คุณเป็นผู้จัดเตรียมทั้งสองอย่าง
ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”GotenbergBridge::convertFile() รับพาธบนดิสก์ โดยจะปรับพาธให้อยู่ในรูปแบบบัญญัติเพื่อป้องกันการเดินผ่านไดเรกทอรี จับคู่นามสกุลไฟล์กับรูปแบบที่รองรับ ตรวจขนาดและชื่อไฟล์ แล้วส่งคำขอแบบ multipart ไปยัง <apiUrl>/forms/libreoffice/convert ส่วน convertString() ใช้เส้นทางเดียวกันสำหรับไบต์ที่คุณมีอยู่แล้ว โดยใช้ชื่อไฟล์เดิมเพื่อให้ตรวจหานามสกุลได้
การตรวจหารูปแบบใช้นามสกุลไฟล์ bridge จะจับคู่ .docx, .xlsx, .pptx, .odt, .ods และ .odp กับรูปแบบที่ตรงกัน และปฏิเสธสิ่งอื่นใดด้วย ValueError ก่อนเกิดการรับส่งข้อมูลทางเครือข่ายใดๆ อ็อบเจกต์ผลลัพธ์จะแสดงรูปแบบต้นทางที่ตรวจพบเป็นค่า enum
bridge รับส่ง HTTP ไปกลับแบบซิงโครนัสหนึ่งครั้ง โดยห่อหุ้มด้วยการตรวจสอบความถูกต้อง bridge ไม่ลองใหม่ ไม่เข้าคิว ไม่แคช และไม่จำกัดอัตรา การควบคุมเหล่านี้เป็นหน้าที่ของแอปพลิเคชันที่เรียกใช้ bridge ให้ถือว่าการแปลงแต่ละครั้งเป็นการเรียกใช้ระยะไกลไปยังบริการที่คุณดำเนินการเองแต่ไม่ได้ควบคุมภายในกระบวนการ และออกแบบให้รองรับความหน่วงและรูปแบบความล้มเหลวของบริการนั้น
bridge รายงานความล้มเหลวเป็นข้อยกเว้นแบบมีชนิด และไม่เคยคืนผลลัพธ์ที่ไม่สมบูรณ์หรือยังไม่ได้ตรวจสอบความถูกต้อง:
- สถานะที่ไม่ใช่
200,Content-Typeที่ไม่มีapplication/pdfหรือเนื้อหาที่ไม่ได้ขึ้นต้นด้วย%PDFจะทำให้เกิดGotenbergConvertExceptionbridge จะคืนผลลัพธ์เฉพาะเมื่อการตรวจทั้งสามอย่างผ่านเท่านั้น - ความล้มเหลวของไคลเอนต์แบบ PSR-18 รวมถึงความล้มเหลวทางเครือข่ายหรือการหมดเวลา จะถูกห่อหุ้มเป็น
GotenbergConvertExceptionโดยมีข้อยกเว้นเดิมเป็นสาเหตุ - ความล้มเหลวในการตรวจสอบความถูกต้อง (URL ที่ไม่ใช่ HTTPS, ที่อยู่ส่วนตัวหรือที่อยู่สงวน, อินพุตเกินขนาด, ชื่อไฟล์ไม่ปลอดภัย) จะทำให้เกิด
RuntimeExceptionก่อนเกิดการรับส่งข้อมูลทางเครือข่ายใดๆ - นามสกุลไฟล์ที่ไม่รู้จักจะทำให้เกิด
ValueErrorก่อนเกิดการรับส่งข้อมูลทางเครือข่ายใดๆ
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”// 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, enum sourceFormat, isValid() (จะเป็นจริงเมื่อเนื้อหาไม่ว่างและขึ้นต้นด้วย %PDF) และ size() สำหรับรายการฟิลด์ทั้งหมด แผนที่คีย์ของ fromArray() และกฎการเลือกการขนส่ง โปรดดูหน้าการกำหนดค่า Gotenberg ที่ลิงก์ไว้ในหัวข้อ See also
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”กำหนดรายละเอียดบริการ เชื่อมต่อ bridge โพรบบริการ แล้วแปลงไฟล์หนึ่งไฟล์
<?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 และจะไม่โยนข้อยกเว้นสำหรับ URL ที่ว่าง ไม่ใช่ 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 ที่ถูกห่อหุ้ม) และกับข้อผิดพลาดของเซิร์ฟเวอร์ที่เป็น idempotent (502, 503, 504) การตอบกลับในกลุ่ม 400 มักหมายความว่าอินพุตไม่ถูกต้อง การลองใหม่จึงมักล้มเหลวแบบเดิม จำกัดจำนวนครั้งของความพยายามทั้งหมดและเวลารวมที่ใช้จริง จำกัดจำนวนการแปลงที่กำลังดำเนินอยู่ให้สอดคล้องกับขีดความสามารถที่การปรับใช้ Gotenberg ของคุณรองรับได้ ตัว bridge เองไม่มีสถานะและปลอดภัยที่จะใช้จากเวิร์กเกอร์หลายตัว แต่บริการมีขีดความสามารถในการแปลงที่จำกัด
กรณีขอบและจุดที่ควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและจุดที่ควรระวัง”- การตรวจหารูปแบบใช้นามสกุลไฟล์ ไฟล์
.docxที่เปลี่ยนชื่อเป็น.txtจะถูกปฏิเสธด้วยValueErrorส่วนไฟล์.txtที่เปลี่ยนชื่อเป็น.docxจะถูกส่งไปยัง Gotenberg และล้มเหลวที่นั่น เมื่อรับไฟล์อัปโหลด ให้ตรวจสอบรูปแบบจริง ไม่ใช่ชื่อไฟล์ fromArray()ผ่อนปรนโดยการออกแบบ โดยจะแทนค่าเริ่มต้นให้กับอินพุตที่ผิดรูปแบบอย่างเงียบๆ ตรวจสอบความถูกต้องของอาร์เรย์ต้นทางในขั้นตอนบูตของคุณ เพื่อให้ URL ที่ขาดหายไปปรากฏตั้งแต่เนิ่นๆ ในรูปแบบของข้อผิดพลาดการกำหนดค่า ไม่ใช่ข้อยกเว้นต่อการแปลงแต่ละครั้ง- ขีดจำกัดขนาดถูกบังคับใช้ภายในกระบวนการ
maxFileSize(ค่าเริ่มต้น 50 MiB) จะถูกตรวจก่อนส่งคำขอ ดังนั้นไฟล์ที่เกินขนาดจึงไม่สิ้นเปลืองขีดความสามารถของบริการ ลดขีดจำกัดให้ตรงกับความต้องการของเอกสารของคุณ ขีดจำกัดที่เล็กกว่าช่วยควบคุมการปฏิเสธบริการได้ประหยัดกว่า - การโพรบมีต้นทุน เรียก
isAvailable()จากเอนด์พอยต์ readiness หรือ health ไม่ใช่ก่อนการแปลงทุกครั้ง การเรียกต่อการแปลงแต่ละครั้งจะเพิ่มอัตราคำขอที่ส่งไปยังบริการเป็นสองเท่าโดยไม่มีประโยชน์ - ไม่มีการแคชภายในกระบวนการ หากมีการแปลงเอกสารเดียวกันซ้ำๆ ให้แคชผลลัพธ์ PDF ไว้ในแอปพลิเคชันของคุณ โดยใช้แฮชเนื้อหาของอินพุตเป็นคีย์
renderTimeMsเป็นค่าที่คุณต้องตั้งเอง ฟิลด์เวลาในผลลัพธ์จะเป็น0.0เว้นแต่การผสานรวมของคุณจะวัดและตั้งค่าให้ จับเวลาการเรียกด้วยตัวเองหากคุณต้องการตัวเลขนั้น
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”การแปลงจะยึดหนึ่งการเชื่อมต่อและหนึ่งเวิร์กเกอร์ LibreOffice ฝั่ง Gotenberg ไว้ตลอดระยะเวลาของคำขอ และการแปลงเอกสาร Office ต้องใช้เวลา ตั้งค่า timeout จากความหน่วงการแปลงที่วัดได้สำหรับเอกสารจริงของคุณ พร้อมเผื่อเวลาไว้ กำหนดให้ต่ำกว่าเกตเวย์ต้นทางใดๆ หรือ max_execution_time ของ PHP เพื่อให้ bridge หมดเวลาก่อนและคุณจะได้ข้อยกเว้นแบบมีชนิดแทนกระบวนการที่ถูกยุติ จำกัดการทำงานพร้อมกันด้วยคิว เซมาฟอร์ หรือพูลเวิร์กเกอร์ที่ปรับขนาดให้พอดีกับขีดความสามารถของบริการ ไม่มีแคชภายในกระบวนการ ให้เพิ่มในแอปพลิเคชันของคุณหากคุณแปลงอินพุตเดียวกันซ้ำๆ
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”- คัดกรอง HTTPS และที่อยู่ก่อนส่ง bridge จะปฏิเสธ URL ที่ไม่ใช่ HTTPS และปลายทางที่รีโซลฟ์ไปยังพื้นที่ที่อยู่ส่วนตัวหรือที่อยู่สงวน ก่อนส่งคำขอใดๆ ออกจากกระบวนการ การลองเรียกใหม่แต่ละครั้งจะรันการตรวจสอบความถูกต้องนั้นซ้ำ ดังนั้นการลองใหม่จึงไม่สามารถเลี่ยงผ่านการป้องกัน SSRF ได้
- การขนส่งแบบปักหมุดเมื่อกำหนดให้ใช้ เมื่อคุณจัดเตรียมแฟกทอรีสำหรับการตอบกลับและหมุด (หรือมีชุด IP ที่รีโซลฟ์แล้ว) bridge จะผูกการเชื่อมต่อกับที่อยู่ที่รีโซลฟ์ได้ บังคับใช้การปักหมุด SPKI ตรวจสอบ peer และ host ใช้การหมดเวลา และปิดการติดตามการเปลี่ยนเส้นทาง กำหนดค่าหมุดสำรองก่อนการหมุนเวียนใบรับรอง
- อย่าเชื่อชนิดเนื้อหาที่ประกาศไว้ของไฟล์อัปโหลด เมื่อรับไฟล์อัปโหลดจากผู้ใช้ ให้ตรวจสอบชนิดไฟล์จริงด้วยตนเอง แผนที่นามสกุลต่อรูปแบบใช้ตัดสินใจเลือกเส้นทาง ไม่ใช่การตรวจสอบความถูกต้องแท้
- ค่าลับถูกปกปิดและไม่เปลี่ยนแปลงค่าได้
apiKeyมี#[SensitiveParameter]และการกำหนดค่าเป็นfinal readonlyดึง token จากตัวจัดการความลับ อย่าคอมมิตลงในโค้ดเด็ดขาด รายการบันทึกการแปลงจะมี URL ชื่อไฟล์ รูปแบบ และความยาวเนื้อหา แต่ไม่มีเนื้อหาไฟล์หรือ token อย่างเด็ดขาด - อย่าเขียนบล็อก
catchที่ว่างเปล่าเด็ดขาด ตัวอย่างแต่ละรายการจะดักจับชนิดที่เจาะจงและบันทึกพร้อมบริบท
สำหรับแบบจำลองความปลอดภัยและการปรับใช้ฉบับเต็ม โปรดดูหน้าความปลอดภัยและการดำเนินงานของ Gotenberg สัญญาการขนส่งแบบ PSR-18 และแนวทางอย่าเชื่อชนิดเนื้อหาถูกปักหมุดไว้กับข้อกำหนดของแต่ละหัวข้อในหน้า production-usage ต้นทาง
ความสอดคล้อง
หัวข้อที่มีชื่อว่า “ความสอดคล้อง”คู่มือนี้ไม่กล่าวอ้างมาตรฐานเชิงบรรทัดฐานใดของตนเอง พฤติกรรมการขนส่งแบบ PSR-18 ของ bridge (ไคลเอนต์จะโยนข้อยกเว้นเฉพาะเมื่อส่งคำขอหรือแยกวิเคราะห์การตอบกลับไม่ได้ ส่วน 4xx/5xx เป็นค่าคืนปกติ) แนวทางการตรวจสอบความถูกต้องของไฟล์อัปโหลด และแบบจำลองการปักหมุด TLS ถูกปักหมุดไว้กับ PSR-18, OWASP และ RFC 7469 ในหน้า production-usage และ configuration ของ Gotenberg ต้นทาง หน้า cookbook นี้กล่าวซ้ำเฉพาะการใช้งานและให้หน้าดังกล่าวเป็นแหล่งอ้างอิง bridge สร้างไบต์ของ PDF แล้วหยุด การลงนาม โปรไฟล์ PDF/A และการทำลายน้ำเป็นเรื่องของการประมวลผลภายหลังของ NextPDF และเป็นความสามารถของรุ่นเชิงพาณิชย์ ไม่ใช่ส่วนหนึ่งของ bridge นี้
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- คืนค่า PDF ที่สร้างขึ้นจากคอนโทรลเลอร์ — คืนค่า PDF ที่แปลงแล้วเป็นการตอบกลับ HTTP
- Gotenberg quickstart — โปรแกรมแปลงที่สมบูรณ์และเรียกใช้ได้
- การกำหนดค่า Gotenberg — ทุกฟิลด์ แผนที่
fromArray()และการเลือกการขนส่ง - การใช้งานจริงของ Gotenberg — ความลับ การหมดเวลา การลองใหม่ การทำงานพร้อมกัน และขอบเขตการประมวลผลภายหลัง