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

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

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

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

Install the latest stable Converter plugin:

bash
dotnet add package Doconut.NET8.Converter

To pin the plugin to the current 26.7.0 release, pass the version separately:

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

Keep 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 ซึ่งจะถูกติดตั้งพร้อมกับแพคเกจตัวดูเอกสารพื้นฐาน

csharp
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) โดยออกแบบ ดังนั้นอินสแตนซ์เดียวจึงปลอดภัยต่อการใช้งานซ้ำหลายคำขอ

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 ใน overload ที่รับสตรีมต้องมีจุดนำหน้า (".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, เอกสารเว็บ) ไปยังชุดเป้าหมายที่อนุญาตของมันเอง อย่า hardcode 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/doconutBase path for the ?convert= endpoints; it must match the ASP.NET branch where UseDoconut() is actually mounted (normally coordinated through MiddlewarePath)
resPathstring/doconut-resAccepted for configuration consistency with other Doconut widgets; the converter widget doesn't currently build any URL from it
maxUploadMbnumber25Client-side pre-check only — rejects an oversized file before uploading. The server enforces its own cap independently and answers 413 if it's exceeded
licenseUrlstring | nullnullWhen set, turns the watermark notice on the result screen into a link to this URL
labelsobject{}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() คืนค่าอินสแตนซ์ของวิดเจ็ตเอง — เก็บอ้างอิงไว้เพื่อควบคุมวิดเจ็ตแบบโปรแกรมเมติก:

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 เป็น token ของเซสชันตัวดูปกติที่อายุการใช้งานตามแคชของตัวดู, ไม่ขึ้นกับ stash

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

โหมดความล้มเหลว แบ่งตามเส้นทาง:

เส้นทางสถานะเมื่อเนื้อหา
any404วิดเจ็ตไม่ได้เปิดใช้งาน (AddConverterWidget() ไม่ได้ถูกเรียก) — ตรวจสอบก่อนเส้นทางใด ๆ ถูก dispatchstatus only
any405ใช้ HTTP verb ผิด (open/run ต้องใช้ POST; download ต้องใช้ GET)status only
open413ไฟล์อัปโหลดใหญ่เกิน MaxUploadMb{ "error": "File is too large." }
open400ไม่มี multipart body, ไม่มีไฟล์, หรือส่วนขยายที่ไม่สามารถแปลงได้{ "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>" } — sanitized the same way as every other Doconut error path; never leaks internal engine names
download400Token ผิดรูปแบบ (ไม่ใช่ GUID)status only
download404ไม่พบหรือ token ดาวน์โหลดหมดอายุstatus only

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

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

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

การแก้ไขปัญหา

อาการตรวจสอบ
ไม่สามารถดึง DocumentConverter ได้การลงทะเบียน ConverterPlugin ต้องทำภายใน AddDoconut()
แอปล้มเหลวขณะเริ่มต้นใบอนุญาตที่โหลดต้องให้สิทธิ์ Converter
การแปลงสตรีมบอกว่าไม่รองรับรูปแบบsourceExtension ต้องมีจุดนำหน้า
JavaScript ของวิดเจ็ตโหลดได้แต่คำขอคืนค่า 404AddConverterWidget() ไม่ได้ถูกเรียก
คำขอของวิดเจ็ตใช้ 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 ด้วยใบอนุญาตการประเมินก่อนซื้อ — เพียงแค่ผลลัพธ์ไบต์เท่านั้นที่เปลี่ยนแปลง.

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