ปลั๊กอินแปลงไฟล์
แปลงเอกสารเป็น 24 รูปแบบเป้าหมาย
ปลั๊กอิน Converter ทำให้ Doconut กลายเป็นบริการแปลงเอกสาร มันเป็นส่วนสำคัญของเอนจินที่อยู่เบื้องหลังฟาซาเด DocumentConverter สาธารณะ และ — หากเปิดใช้งาน — วิดเจ็ตแบบ drop‑in ที่มีสัญญา HTTP ของตนเอง เพื่อให้คุณสามารถแปลงเอกสารจาก C#, จากวิดเจ็ต, หรือจากส่วนหน้า (frontend) ที่คุณเขียนเองได้
ติดตั้งแพคเกจ
ติดตั้งปลั๊กอิน Converter รุ่นเสถียรล่าสุด:
dotnet add package Doconut.NET6.Converterหากต้องการล็อกเวอร์ชันของปลั๊กอินให้ตรงกับรุ่น 26.7.0 ปัจจุบัน ให้ระบุเวอร์ชันแยกต่างหาก:
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 พื้นฐาน
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});การเรียกนี้จะโยนข้อยกเว้นในขณะเริ่มต้นหากไม่มีใบอนุญาต, มีไฟล์
TRIALเก่า, หรือใบอนุญาตที่ไม่ใช่แบบชั่วคราวซึ่งไม่ได้ให้ความสามารถConverter—InvalidOperationExceptionจะถูกยกจากภายในAddDoconut(), ก่อนที่แอปจะให้บริการคำขอ. การลงทะเบียนแบบ Demo/NFR ชั่วคราวจะได้รับการยอมรับ; หลังจากหมดอายุตามปฏิทิน, การแปลงยังคงใช้งานได้พร้อมผลลัพธ์ที่มีลายน้ำ. ไม่มีระดับฟรีแบบเงียบ. ดู การตั้งค่าใบอนุญาต เพื่อดูวิธีการโหลดใบอนุญาต
แปลงจาก C#
การแปลงแต่ละครั้งจะคืนค่า MemoryStream ที่สามารถเลื่อนตำแหน่งได้และอยู่ที่ตำแหน่ง 0 พร้อมให้อ่านหรือคัดลอกทันที ให้ดึง DocumentConverter จาก DI ทุกที่ที่ต้องการ — มันเป็นสเตตเลสโดยออกแบบ ดังนั้นอินสแตนซ์เดียวจึงปลอดภัยต่อการใช้ซ้ำระหว่างคำขอ
// Inject DocumentConverter; its constructor is internal, so never `new` it.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);// 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);Stream html = await converter.WordToHtmlAsync("report.docx", ct);Stream docx = await converter.HtmlToWordAsync(html, ConversionTarget.Docx, ct);สองรายละเอียดที่มักทำผิดง่าย: sourceExtension ในโอเวอร์โหลดที่รับสตรีมต้องมีจุดนำหน้า (".xlsx" ไม่ใช่ "xlsx") — ตัวแปลงจะจับคู่กับแคตาล็อกฟอร์แมตและส่วนขยายที่ไม่มีจุดจะไม่สามารถแก้ได้. อีกทั้งแม้ชื่อจะบอกว่า WordToHtmlAsync แต่จริง ๆ แล้วคืนค่า Task<Stream> ไม่ใช่ Task<string> — คุณจะได้รับเอกสาร HTML (ภาพฝังเป็น Base64) เป็นสตรีม เหมือนกับผลลัพธ์การแปลงทุกประเภทอื่น ๆ
รูปแบบเป้าหมาย
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 และถูกปิดใช้งานโดยค่าเริ่มต้น — ปลอดภัยโดยดีฟอลต์ เปิดใช้งานที่ฝั่งเซิร์ฟเวอร์พร้อมกับการลงทะเบียนปลั๊กอิน
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddConverterWidget(widget =>
{
widget.MaxUploadMb = 25;
});
});<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):
| ตัวเลือก | ชนิด | ค่าเริ่มต้น | หมายเหตุ |
|---|---|---|---|
basePath | string | /doconut | เส้นทางฐานสำหรับเอ็นด์พอยต์ ?convert=; ต้องตรงกับสาขา ASP.NET ที่ UseDoconut() ถูกเมานท์จริง (โดยปกติประสานผ่าน MiddlewarePath) |
resPath | string | /doconut-res | ยอมรับเพื่อความสอดคล้องกับวิดเจ็ต Doconut อื่น; วิดเจ็ตแปลงไฟล์ในขณะนี้ไม่ได้สร้าง URL ใดจากค่านี้ |
maxUploadMb | number | 25 | ตรวจสอบล่วงหน้าที่ฝั่งไคลเอนต์เท่านั้น — ปฏิเสธไฟล์ที่ใหญ่เกินขนาดก่อนอัปโหลด. เซิร์ฟเวอร์บังคับขีดจำกัดของตนเองแยกจากกันและตอบ 413 หากเกิน |
licenseUrl | string | null | null | หากตั้งค่า, จะทำให้ข้อความลายน้ำบนหน้าผลลัพธ์กลายเป็นลิงก์ไปยัง URL นี้ |
labels | object | {} | แทนที่สตริงเริ่มต้นภาษาอังกฤษของวิดเจ็ต (ข้อความดรอป, ปุ่ม, การประกาศ 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() จะคืนค่าอินสแตนซ์ของวิดเจ็ตเอง — เก็บอ็อบเจ็กต์นี้ไว้เพื่อควบคุมวิดเจ็ตด้วยโปรแกรม:
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> | แปลงไฟล์ต้นทางที่เก็บไว้เป็น target | 200 — { 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) | มีเฉพาะสถานะ |
open | 413 | ไฟล์ที่อัปโหลดใหญ่เกิน MaxUploadMb | { "error": "File is too large." } |
open | 400 | ไม่มี body แบบ multipart, ไม่มีไฟล์, หรือส่วนขยายของแหล่งที่ไม่สามารถแปลงได้ | { "error": "..." } |
run | 400 | token ผิดรูปแบบ (ไม่ใช่ GUID) หรือ target ไม่สามารถแปลงเป็น ConversionTarget | { "error": "Invalid token." } / { "error": "Unknown target format." } |
run | 400 | target ไม่อยู่ใน allowedTargets ของแหล่ง | { "error": "That target format is not available for this file." } |
run | 404 | การอัปโหลดที่เก็บไว้หมดอายุ (TTL 30 นาที) หรือ token ไม่เคยเปิด | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | การประมวลผลล้มเหลวภายใน | { "error": "<sanitized message>" } — ทำความสะอาดแบบเดียวกับเส้นทางข้อผิดพลาดของ Doconut ทุกเส้นทาง; ไม่เปิดเผยชื่อเอนจินภายใน |
download | 400 | token ผิดรูปแบบ (ไม่ใช่ GUID) | มีเฉพาะสถานะ |
download | 404 | token ดาวน์โหลดไม่รู้จักหรือหมดอายุ | มีเฉพาะสถานะ |
ความเป็นเจ้าของทรัพยากร (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 ด้วยใบอนุญาตการประเมินก่อนซื้อ — เพียงแค่ไบต์ผลลัพธ์ที่เปลี่ยนไป.
หน้านี้เป็นประโยชน์หรือไม่?