ปลั๊กอินแปลงไฟล์

แปลงเอกสารเป็น 24 รูปแบบเป้าหมาย

ปลั๊กอิน Converter ทำให้ Doconut กลายเป็นบริการแปลงเอกสาร มันเป็นส่วนสำคัญของเอนจินที่อยู่เบื้องหลังฟาซาเด DocumentConverter สาธารณะ และ — หากเปิดใช้งาน — วิดเจ็ตแบบ drop‑in ที่มีสัญญา HTTP ของตนเอง เพื่อให้คุณสามารถแปลงเอกสารจาก C#, จากวิดเจ็ต, หรือจากส่วนหน้า (frontend) ที่คุณเขียนเองได้

ติดตั้งแพคเกจ

ติดตั้งปลั๊กอิน Converter รุ่นเสถียรล่าสุด:

bash
dotnet add package Doconut.NET6.Converter

หากต้องการล็อกเวอร์ชันของปลั๊กอินให้ตรงกับรุ่น 26.7.0 ปัจจุบัน ให้ระบุเวอร์ชันแยกต่างหาก:

bash
dotnet add package Doconut.NET6.Converter --version 26.7.0

ให้รักษาเวอร์ชันของแพคเกจ Converter ให้ตรงกับ Doconut.NET6 เสมอ แพคเกจไอดีคือ Doconut.NET6.Converter; .26.7.0 ปรากฏเฉพาะในชื่อไฟล์ .nupkg ที่ดาวน์โหลดมา

ลงทะเบียนปลั๊กอิน

ไม่มีเมธอด AddConverter() — โมเดลปลั๊กอินของ Doconut มีรูปแบบเดียวกัน ทุกปลั๊กอินรวมถึง Converter จะลงทะเบียนด้วยวิธีเดียวกัน: เรียก AddPlugin<TPlugin>() ภายใน AddDoconut() ConverterPlugin มาพร้อมกับแพคเกจ NuGet ของตนเอง Doconut.NET6.Converter ซึ่งติดตั้งพร้อมกับแพคเกจ viewer พื้นฐาน

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});

การเรียกนี้จะโยนข้อยกเว้นในขณะเริ่มต้นหากไม่มีใบอนุญาต, มีไฟล์ TRIAL เก่า, หรือใบอนุญาตที่ไม่ใช่แบบชั่วคราวซึ่งไม่ได้ให้ความสามารถ ConverterInvalidOperationException จะถูกยกจากภายใน AddDoconut(), ก่อนที่แอปจะให้บริการคำขอ. การลงทะเบียนแบบ Demo/NFR ชั่วคราวจะได้รับการยอมรับ; หลังจากหมดอายุตามปฏิทิน, การแปลงยังคงใช้งานได้พร้อมผลลัพธ์ที่มีลายน้ำ. ไม่มีระดับฟรีแบบเงียบ. ดู การตั้งค่าใบอนุญาต เพื่อดูวิธีการโหลดใบอนุญาต

แปลงจาก C#

การแปลงแต่ละครั้งจะคืนค่า MemoryStream ที่สามารถเลื่อนตำแหน่งได้และอยู่ที่ตำแหน่ง 0 พร้อมให้อ่านหรือคัดลอกทันที ให้ดึง DocumentConverter จาก DI ทุกที่ที่ต้องการ — มันเป็นสเตตเลสโดยออกแบบ ดังนั้นอินสแตนซ์เดียวจึงปลอดภัยต่อการใช้ซ้ำระหว่างคำขอ

csharp
// Inject DocumentConverter; its constructor is internal, so never `new` it.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);
csharp
// sourceExtension includes the leading dot. password is null unless the document is protected.
Stream png = await converter.ConvertAsync(upload, ".xlsx", ConversionTarget.Png, password: null, ct: ct);
csharp
Stream html = await converter.WordToHtmlAsync("report.docx", ct);
csharp
Stream docx = await converter.HtmlToWordAsync(html, ConversionTarget.Docx, ct);

สองรายละเอียดที่มักทำผิดง่าย: sourceExtension ในโอเวอร์โหลดที่รับสตรีมต้องมีจุดนำหน้า (".xlsx" ไม่ใช่ "xlsx") — ตัวแปลงจะจับคู่กับแคตาล็อกฟอร์แมตและส่วนขยายที่ไม่มีจุดจะไม่สามารถแก้ได้. อีกทั้งแม้ชื่อจะบอกว่า WordToHtmlAsync แต่จริง ๆ แล้วคืนค่า Task<Stream> ไม่ใช่ Task<string> — คุณจะได้รับเอกสาร HTML (ภาพฝังเป็น Base64) เป็นสตรีม เหมือนกับผลลัพธ์การแปลงทุกประเภทอื่น ๆ

รูปแบบเป้าหมาย

text
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, Webp

ไม่ใช่ทุกแหล่งจะสามารถแปลงเป็นทุกเป้าหมาย — ปลั๊กอินจะแมปตระกูลฟอร์แมตของแหล่ง (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project/Task, PSD, web document) ไปยังชุดเป้าหมายที่อนุญาตของตนเอง อย่าฮาร์ดโค้ด enum นี้เป็นรายการเป้าหมายของ UI ของคุณ: ?convert=open จะคืนค่า allowedTargets ที่แท้จริงสำหรับไฟล์ที่เพิ่งอัปโหลด และควรใช้ค่านั้นเป็นตัวขับเคลื่อนตัวเลือก

วิดเจ็ตแบบ drop‑in

เอ็นด์พอยต์ ?convert=open|run|download ของวิดเจ็ตเป็นแบบ opt‑in และถูกปิดใช้งานโดยค่าเริ่มต้น — ปลอดภัยโดยดีฟอลต์ เปิดใช้งานที่ฝั่งเซิร์ฟเวอร์พร้อมกับการลงทะเบียนปลั๊กอิน

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
    options.AddConverterWidget(widget =>
    {
        widget.MaxUploadMb = 25;
    });
});
html
<div id="doconut-convert"></div>
<script src="/doconut-res/js/doconutConverter.js"></script>
<script>
  Doconut.convert('#doconut-convert', { basePath: '/doconut', resPath: '/doconut-res', maxUploadMb: 25 });
</script>

หากไม่ได้เรียก AddConverterWidget() เอ็นด์พอยต์สามตัว ?convert= จะตอบ 404 — แต่ไฟล์ JS เองยังคงให้บริการอยู่ (เป็นทรัพยากรสแตติกแบบฝัง; เพียงเอ็นด์พอยต์ที่มันติดต่อเท่านั้นที่ถูกกั้น). AddConverterWidget() ยังต้องการให้ปลั๊กอิน Converter ถูกลงทะเบียนและมีใบอนุญาตที่ให้ Converter — มันไม่ได้ให้สิทธิ์การแปลงโดยอัตโนมัติ

ปรับแต่งวิดเจ็ต

ตัวเลือกเริ่มต้นที่ส่งให้ Doconut.convert(selector, options):

ตัวเลือกชนิดค่าเริ่มต้นหมายเหตุ
basePathstring/doconutเส้นทางฐานสำหรับเอ็นด์พอยต์ ?convert=; ต้องตรงกับสาขา ASP.NET ที่ UseDoconut() ถูกเมานท์จริง (โดยปกติประสานผ่าน MiddlewarePath)
resPathstring/doconut-resยอมรับเพื่อความสอดคล้องกับวิดเจ็ต Doconut อื่น; วิดเจ็ตแปลงไฟล์ในขณะนี้ไม่ได้สร้าง URL ใดจากค่านี้
maxUploadMbnumber25ตรวจสอบล่วงหน้าที่ฝั่งไคลเอนต์เท่านั้น — ปฏิเสธไฟล์ที่ใหญ่เกินขนาดก่อนอัปโหลด. เซิร์ฟเวอร์บังคับขีดจำกัดของตนเองแยกจากกันและตอบ 413 หากเกิน
licenseUrlstring | nullnullหากตั้งค่า, จะทำให้ข้อความลายน้ำบนหน้าผลลัพธ์กลายเป็นลิงก์ไปยัง URL นี้
labelsobject{}แทนที่สตริงเริ่มต้นภาษาอังกฤษของวิดเจ็ต (ข้อความดรอป, ปุ่ม, การประกาศ aria‑live, ข้อความผิดพลาด) ด้วยค่าที่กำหนด

คอลแบ็ก:

คอลแบ็กเกิดเมื่อพayload
onReady()วิดเจ็ตได้เรนเดอร์หน้าจอว่าง/ดรอปแล้ว
onSourceLoaded({ token, pages, sourceExt, allowedTargets })?convert=open สำเร็จtoken ของเซสชันแหล่ง, จำนวนหน้า, ส่วนขยายของแหล่ง (ไม่มีจุดนำหน้า), รายการเป้าหมายที่อนุญาต
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target })?convert=run สำเร็จฟิลด์เดียวกับการตอบกลับของ run, พร้อม target ที่ร้องขอ
onDownload({ downloadName, downloadToken })ผู้ใช้คลิกลิงก์ดาวน์โหลดเกิดพร้อมกับการดาวน์โหลดของเบราว์เซอร์ — ไม่ได้ดักหรือแทนที่
onError({ phase, message })คำขอ open หรือ run ล้มเหลวphase เป็น 'open' หรือ 'run'; message คือข้อความข้อผิดพลาดที่ทำความสะอาดแล้ว (หรือข้อความฝั่งไคลเอนต์สำหรับการตรวจสอบขนาดอัปโหลด)

Doconut.convert() จะคืนค่าอินสแตนซ์ของวิดเจ็ตเอง — เก็บอ็อบเจ็กต์นี้ไว้เพื่อควบคุมวิดเจ็ตด้วยโปรแกรม:

javascript
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset();         // กลับไปที่หน้าจอว่าง/ดรอป; ไม่ทำให้ onReady เกิดใหม่
conv.loadFile(file);  // เริ่มกระบวนการด้วยอ็อบเจ็กต์ File; ไม่มีผลหากไม่ได้อยู่ในสถานะว่าง
conv.destroy();       // ลบ listener, ล้าง mount; อินสแตนซ์จะใช้ไม่ได้หลังจากนี้

สร้างส่วนหน้า (frontend) ของคุณเอง

วิดเจ็ตเป็นเพียงไคลเอนต์สำหรับสัญญา HTTP นี้ — คุณสามารถสร้างส่วนหน้าเองโดยติดต่อสัญญานี้โดยตรงเพื่อ UX ที่แตกต่างกัน ทั้งสามเส้นทางอยู่ภายใต้สาขา ASP.NET ที่ UseDoconut() ถูกเมานท์ (โดยปกติคือ /doconut):

เส้นทางวัตถุประสงค์การตอบสนองเมื่อสำเร็จ
POST ?convert=open (multipart, field file)อัปโหลดและเปิดเอกสารต้นทางเพื่อแสดงตัวอย่าง200{ token, pages, sourceExt, allowedTargets }
POST ?token=<token>&convert=run&target=<ext>แปลงไฟล์ต้นทางที่เก็บไว้เป็น target200{ downloadToken, resultToken, resultPages, downloadName, watermarked }
GET ?convert=download&token=<downloadToken>สตรีมไฟล์ที่แปลงแล้ว200 — ไบต์ไฟล์, Content‑Disposition: attachment, Cache‑Control: no‑store

ไบต์ของแหล่งที่อัปโหลดจะถูกเก็บไว้ฝั่งเซิร์ฟเวอร์เป็นเวลา 30 นาที; หลังจากช่วงเวลานั้น run จะตอบ 404 และไฟล์ต้องถูกเปิดใหม่ ผลลัพธ์ที่แปลงแล้วอยู่ใน stash เดียวกัน — downloadToken จะได้รับหน้าต่าง 30 นาทีใหม่เมื่อการแปลงเสร็จ — ส่วน resultToken เป็นโทเคนเซสชันของ viewer ธรรมดาที่อายุการใช้งานตามแคชของ viewer, ไม่ขึ้นกับ stash

sourceExt ในการตอบ open จะไม่มีจุดนำหน้า (เช่น "docx") — ซึ่งตรงข้ามกับพารามิเตอร์ sourceExtension ของ DocumentConverter.ConvertAsync ที่ต้องมีจุดนำหน้า

โหมดความล้มเหลว (Failure modes) แบ่งตามเส้นทาง

เส้นทางสถานะเมื่อไรเนื้อหา
ใด ๆ404วิดเจ็ตไม่ได้เปิดใช้งาน (AddConverterWidget() ไม่ได้ถูกเรียก) — ตรวจสอบก่อนเส้นทางทั้งสามจะถูกส่งต่อมีเฉพาะสถานะ
ใด ๆ405ใช้ HTTP verb ผิด (open/run ต้องใช้ POST; download ต้องใช้ GET)มีเฉพาะสถานะ
open413ไฟล์ที่อัปโหลดใหญ่เกิน MaxUploadMb{ "error": "File is too large." }
open400ไม่มี body แบบ multipart, ไม่มีไฟล์, หรือส่วนขยายของแหล่งที่ไม่สามารถแปลงได้{ "error": "..." }
run400token ผิดรูปแบบ (ไม่ใช่ GUID) หรือ target ไม่สามารถแปลงเป็น ConversionTarget{ "error": "Invalid token." } / { "error": "Unknown target format." }
run400target ไม่อยู่ใน allowedTargets ของแหล่ง{ "error": "That target format is not available for this file." }
run404การอัปโหลดที่เก็บไว้หมดอายุ (TTL 30 นาที) หรือ token ไม่เคยเปิด{ "error": "Upload expired — please re-open the file." }
open, run500การประมวลผลล้มเหลวภายใน{ "error": "<sanitized message>" } — ทำความสะอาดแบบเดียวกับเส้นทางข้อผิดพลาดของ Doconut ทุกเส้นทาง; ไม่เปิดเผยชื่อเอนจินภายใน
download400token ผิดรูปแบบ (ไม่ใช่ GUID)มีเฉพาะสถานะ
download404token ดาวน์โหลดไม่รู้จักหรือหมดอายุมีเฉพาะสถานะ

ความเป็นเจ้าของทรัพยากร (Resource ownership)

ตัวแปลงจะคืนค่า MemoryStream ที่สามารถเลื่อนตำแหน่งได้และอยู่ที่ตำแหน่งศูนย์ ผู้เรียกใช้เป็นเจ้าของสตรีมนี้และควรทำ Dispose หลังจากคัดลอกหรือคืนค่าข้อมูลของมัน DocumentConverter เองเป็นสเตตเลสและดึงจาก dependency injection; อย่าสร้างหรือทำ Dispose ตัวบริการด้วยตนเอง

สำหรับวิดเจ็ตบนเว็บ stash ของการอัปโหลดและการดาวน์โหลดมี TTL แยกกัน 30 นาที resultToken ของ viewer จะอายุตามเซสชันของ viewer แทน การปิดผลลัพธ์ของ viewer จะไม่ลบ stash การดาวน์โหลดที่ยังคงมีอายุอยู่ และการรีเซ็ตวิดเจ็ตในเบราว์เซอร์จะไม่ขยาย TTL ใด ๆ ทั้งหมด

การแก้ไขปัญหา (Troubleshooting)

อาการตรวจสอบ
ไม่สามารถดึง DocumentConverter ได้การลงทะเบียน ConverterPlugin ต้องทำภายใน AddDoconut()
แอปล้มเหลวขณะเริ่มต้นใบอนุญาตที่โหลดต้องให้สิทธิ์ Converter
การแปลงสตรีมบอกว่าไม่รองรับฟอร์แมตsourceExtension ต้องมีจุดนำหน้า
JavaScript ของวิดเจ็ตโหลดได้แต่คำขอคืนค่า 404ไม่ได้เรียก AddConverterWidget()
คำขอของวิดเจ็ตใช้ URL ผิดbasePath ต้องตรงกับสาขาที่ UseDoconut() ถูกแมป
ไม่พบเป้าหมายใช้ allowedTargets ที่คืนจาก convert=open; ไม่ใช่ทุกแหล่งจะรองรับทุก enum target
การดาวน์โหลดหมดอายุทำ convert=open/convert=run ใหม่; โทเคน stash มีอายุชั่วคราวโดยเจตนา

การใส่ลายน้ำ (Watermarking)

เมื่อ ConverterPlugin ถูกลงทะเบียน ใบอนุญาตของโฮสต์จะอยู่ในหนึ่งในสามสถานะต่อไปนี้:

สถานะใบอนุญาตเกตเริ่มต้นผลลัพธ์การแปลง
ใบอนุญาตผู้ชมแบบชำระเงินที่ให้ Converter และอยู่ในช่วงเวลาที่ใช้งานได้ผ่านสะอาด — watermarked: false
ใบอนุญาตการประเมิน (demo/NFR) ที่ยังใช้งานได้ผ่านแปลงสำเร็จ, มีลายน้ำการประเมิน — watermarked: true
ไม่มีใบอนุญาต, ไฟล์ TRIAL เก่า, หรือใบอนุญาตที่ไม่ใช่แบบชั่วคราวซึ่งไม่ได้ให้ Converterแอปไม่เริ่มทำงาน — เกตเริ่มต้นที่อธิบายข้างต้นโยนข้อยกเว้น
ใบอนุญาตชั่วคราว/เดโมที่หมดอายุการลงทะเบียนยังคงอยู่หลังหมดอายุแปลงพร้อมลายน้ำการประเมิน — watermarked: true

เส้นทางการเรียกทั้งสองคำนวณค่าสถานะนี้จากกฎเดียวกัน: ฟาซาเด C# DocumentConverter สรุปจากสถานะ IsViewerLicensed และ IsTemporary ของใบอนุญาต, ส่วนตัวจัดการ ?convert=run ของวิดเจ็ตทำการตรวจสอบเทียบเท่า (IsViewerLicensed && !IsTrial && !IsTemporary) เพื่อเติมฟิลด์ watermarked ที่ส่งกลับ. คุณสามารถสร้างและทดสอบการบูรณาการแบบ end‑to‑end ด้วยใบอนุญาตการประเมินก่อนซื้อ — เพียงแค่ไบต์ผลลัพธ์ที่เปลี่ยนไป.

หน้านี้เป็นประโยชน์หรือไม่?