ปลั๊กอินแปลงไฟล์
แปลงเอกสารเป็น 24 รูปแบบเป้าหมาย
ปลั๊กอิน Converter ทำให้ Doconut กลายเป็นบริการแปลงเอกสาร มันเป็นส่วนสำคัญของเอนจินที่อยู่เบื้องหลังฟาซาเด DocumentConverter สาธารณะ และ — ตามการเลือก — วิดเจ็ตแบบ drop‑in ที่มีสัญญา HTTP ของตัวเอง ทำให้คุณสามารถแปลงเอกสารจาก C#, จากวิดเจ็ต, หรือจากส่วนหน้า (frontend) ที่คุณเขียนเองได้
ติดตั้งแพคเกจ
Install the latest stable Converter plugin:
dotnet add package Doconut.NET8.ConverterTo pin the plugin to the current 26.7.0 release, pass the version separately:
dotnet add package Doconut.NET8.Converter --version 26.7.0Keep the Converter package at the same version as Doconut.NET8. The package ID is
Doconut.NET8.Converter; .26.7.0 appears only in the downloaded .nupkg filename.
ลงทะเบียนปลั๊กอิน
ไม่มีเมธอด AddConverter() — โมเดลปลั๊กอินของ Doconut มีความสอดคล้องกันทุกตัว ปลั๊กอินทั้งหมด รวมถึง Converter ด้วย จะลงทะเบียนในรูปแบบเดียวกัน: เรียก AddPlugin<TPlugin>() ภายใน AddDoconut() ConverterPlugin มาพร้อมกับแพคเกจ NuGet ของมันเอง คือ Doconut.NET8.Converter ซึ่งจะถูกติดตั้งพร้อมกับแพคเกจตัวดูเอกสารพื้นฐาน
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 ทุกที่ที่ต้องการ — มันไม่มีสถานะ (stateless) โดยออกแบบ ดังนั้นอินสแตนซ์เดียวจึงปลอดภัยต่อการใช้งานซ้ำหลายคำขอ
// 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 ใน overload ที่รับสตรีมต้องมีจุดนำหน้า (".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, เอกสารเว็บ) ไปยังชุดเป้าหมายที่อนุญาตของมันเอง อย่า hardcode 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 | Base path for the ?convert= endpoints; it must match the ASP.NET branch where UseDoconut() is actually mounted (normally coordinated through MiddlewarePath) |
resPath | string | /doconut-res | Accepted for configuration consistency with other Doconut widgets; the converter widget doesn't currently build any URL from it |
maxUploadMb | number | 25 | Client-side pre-check only — rejects an oversized file before uploading. The server enforces its own cap independently and answers 413 if it's exceeded |
licenseUrl | string | null | null | When set, turns the watermark notice on the result screen into a link to this URL |
labels | object | {} | Overrides any subset of the widget's English default strings (drop text, buttons, aria-live announcements, error messages) |
คอลแบ็ก:
| คอลแบ็ก | เกิดขึ้นเมื่อ | ข้อมูลที่ส่งกลับ |
|---|---|---|
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 เป็น token ของเซสชันตัวดูปกติที่อายุการใช้งานตามแคชของตัวดู, ไม่ขึ้นกับ stash
sourceExt ในการตอบ open จะไม่มีจุดนำหน้า (เช่น "docx") — ตรงกันข้ามกับพารามิเตอร์ sourceExtension ของ DocumentConverter.ConvertAsync ที่ต้องมีจุดนำหน้า
โหมดความล้มเหลว แบ่งตามเส้นทาง:
| เส้นทาง | สถานะ | เมื่อ | เนื้อหา |
|---|---|---|---|
| any | 404 | วิดเจ็ตไม่ได้เปิดใช้งาน (AddConverterWidget() ไม่ได้ถูกเรียก) — ตรวจสอบก่อนเส้นทางใด ๆ ถูก dispatch | status only |
| any | 405 | ใช้ HTTP verb ผิด (open/run ต้องใช้ POST; download ต้องใช้ GET) | status only |
open | 413 | ไฟล์อัปโหลดใหญ่เกิน MaxUploadMb | { "error": "File is too large." } |
open | 400 | ไม่มี multipart body, ไม่มีไฟล์, หรือส่วนขยายที่ไม่สามารถแปลงได้ | { "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>" } — sanitized the same way as every other Doconut error path; never leaks internal engine names |
download | 400 | Token ผิดรูปแบบ (ไม่ใช่ GUID) | status only |
download | 404 | ไม่พบหรือ token ดาวน์โหลดหมดอายุ | status only |
ความเป็นเจ้าของทรัพยากร
ตัวแปลงจะคืนค่า MemoryStream ที่สามารถเลื่อนตำแหน่งได้และอยู่ที่ตำแหน่งศูนย์ ผู้เรียกเป็นเจ้าของสตรีมนี้และควรทำ dispose หลังจากคัดลอกหรือคืนค่าเนื้อหาแล้ว บริการ DocumentConverter เองไม่มีสถานะและถูกดึงจาก dependency injection; อย่าสร้างหรือทำ dispose ด้วยตนเอง
สำหรับวิดเจ็ตบนเว็บ stash ของการอัปโหลดและดาวน์โหลดมี TTL 30 นาทีแยกกัน token resultToken ของตัวดูจะอายุตามเซสชันของตัวดู การปิดผลลัพธ์ของตัวดูจะไม่ลบ stash ของการดาวน์โหลดที่ยังคงมีอายุ, และการรีเซ็ตวิดเจ็ตในเบราว์เซอร์จะไม่ขยาย TTL ใด ๆ ทั้งสอง
การแก้ไขปัญหา
| อาการ | ตรวจสอบ |
|---|---|
ไม่สามารถดึง DocumentConverter ได้ | การลงทะเบียน ConverterPlugin ต้องทำภายใน AddDoconut() |
| แอปล้มเหลวขณะเริ่มต้น | ใบอนุญาตที่โหลดต้องให้สิทธิ์ Converter |
| การแปลงสตรีมบอกว่าไม่รองรับรูปแบบ | sourceExtension ต้องมีจุดนำหน้า |
| JavaScript ของวิดเจ็ตโหลดได้แต่คำขอคืนค่า 404 | AddConverterWidget() ไม่ได้ถูกเรียก |
| คำขอของวิดเจ็ตใช้ URL ผิด | basePath ต้องตรงกับสาขาที่ UseDoconut() ถูกแมป |
| ไม่พบเป้าหมาย | ใช้ allowedTargets ที่คืนจาก convert=open; ไม่ใช่ทุกแหล่งข้อมูลจะสนับสนุนทุก enum target |
| ดาวน์โหลดหมดอายุ | ทำ convert=open/convert=run ใหม่; token ของ stash มีอายุชั่วคราวโดยเจตนา |
การใส่น้ำลายน้ำ
เมื่อ ConverterPlugin ถูกลงทะเบียน ใบอนุญาตของโฮสต์จะอยู่ในหนึ่งในสามสถานะ:
| สถานะใบอนุญาต | ประตูเริ่มต้น | ผลลัพธ์การแปลง |
|---|---|---|
ใบอนุญาตผู้ดูที่จ่ายเงินและให้สิทธิ์ Converter อยู่ในช่วงเวลาที่มีผล | ผ่าน | สะอาด — watermarked: false |
| ใบอนุญาตการประเมิน (demo/NFR) ที่ยังใช้งานได้ | ผ่าน | แปลงสำเร็จ พร้อมลายน้ำการประเมิน — watermarked: true |
ไม่มีใบอนุญาต, ไฟล์ TRIAL เก่า, หรือใบอนุญาตที่ไม่ใช่แบบชั่วคราวและไม่ได้ให้สิทธิ์ Converter | แอปไม่เริ่ม — ประตูเริ่มต้นข้างต้นจะโยนข้อยกเว้น | — |
| ใบอนุญาตชั่วคราว/Demo ที่หมดอายุ | การลงทะเบียนยังคงอยู่หลังหมดอายุ | แปลงพร้อมลายน้ำการประเมิน — watermarked: true |
เส้นทางการเรียกทั้งสองคำนวณค่าสถานะจากกฎเดียวกัน: ฟาซาเด C# DocumentConverter ดึงค่าจากสถานะ IsViewerLicensed และ IsTemporary ของใบอนุญาต, ส่วน handler ?convert=run ของวิดเจ็ตทำการตรวจสอบเทียบเท่า (IsViewerLicensed && !IsTrial && !IsTemporary) เพื่อเติมฟิลด์ watermarked ที่ส่งกลับ การรวมเข้ากับระบบสามารถสร้างและทดสอบแบบ end‑to‑end ด้วยใบอนุญาตการประเมินก่อนซื้อ — เพียงแค่ผลลัพธ์ไบต์เท่านั้นที่เปลี่ยนแปลง.
หน้านี้เป็นประโยชน์หรือไม่?