ปลั๊กอินแปลงไฟล์
แปลงเอกสารเป็น 24 รูปแบบเป้าหมาย
ปลั๊กอิน Converter ทำให้ Doconut กลายเป็นบริการแปลงเอกสาร มันเป็นส่วนของเอนจินที่อยู่เบื้องหลังฟาซาเด DocumentConverter สาธารณะและ — ตามที่เลือก — วิดเจ็ตแบบ drop‑in ที่ให้บริการโดย DocImage.axd ทำให้คุณสามารถแปลงเอกสารจาก C#, จากวิดเจ็ต, หรือจากส่วนหน้า (frontend) ที่คุณเขียนเองได้.
ติดตั้งแพคเกจ
Install-Package Doconut.NETFramework.Converterเก็บแพคเกจ Converter ให้เป็นเวอร์ชันเดียวกับ Doconut.NETFramework.
ลงทะเบียนปลั๊กอิน
ทุกปลั๊กอินจะลงทะเบียนด้วยวิธีเดียวกัน: AddPlugin<TPlugin>() ใน DoconutHost.Initialize.
Doconut.DoconutHost.Initialize(options =>
{
options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});หากไม่มีใบอนุญาตที่ใช้งานได้ให้ความสามารถ
Converter— ไม่มีใบอนุญาต, ไฟล์TRIALเก่า, หรือใบอนุญาตที่ไม่มีความสามารถนี้ —DoconutHost.Initializeจะโยนข้อผิดพลาดจากApplication_Start. ใน System.Web นั่นหมายความว่าทุกคำขอจะตอบด้วย500ว่างเปล่า, และสาเหตุจะอยู่ในบันทึกเหตุการณ์ของ Windows (source ASP.NET) เท่านั้น. ใบอนุญาต Demo/NFR ชั่วคราวจะได้รับการยอมรับ. ดู ตั้งค่าลิขสิทธิ์.
แปลงจาก C#
การแปลงแต่ละครั้งจะคืนค่า MemoryStream ที่สามารถเลื่อนตำแหน่งได้และเริ่มที่ตำแหน่ง 0. DocumentConverter ไม่มีสถานะ: ดึงมันจาก DoconutHost.Services ที่ใดก็ได้ที่คุณต้องการและใช้ซ้ำได้อย่างอิสระ.
// Resolve DocumentConverter from DoconutHost.Services; 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) จะมาถึงเป็นสตรีมเช่นผลลัพธ์อื่น ๆ ทุกอย่าง.
ในคอนโทรลเลอร์ MVC 5
ทำให้แอคชันเป็นแบบอะซิงโครนัสและ await การแปลง:
[HttpPost]
public async Task<ActionResult> ToPdf(HttpPostedFileBase file)
{
var converter = Doconut.DoconutHost.Services.GetRequiredService<DocumentConverter>();
Stream pdf = await converter.ConvertAsync(
file.InputStream, Path.GetExtension(file.FileName), ConversionTarget.Pdf,
password: null, ct: Response.ClientDisconnectedToken);
return File(pdf, "application/pdf", Path.GetFileNameWithoutExtension(file.FileName) + ".pdf");
}ใน Web Forms: อย่าบล็อกการแปลง
หน้า Web Forms ทำงานบนบริบทคำขอแบบ single‑threaded. ConvertAsync จะทำงานต่อบนบริบทนั้นเมื่อเสร็จ, ดังนั้นหน้าที่รอผลแบบ synchronous — .Result, .Wait(), .GetAwaiter().GetResult() — จะยึดเธรดที่การแปลงต้องการเพื่อทำให้เสร็จ. คำขอจะไม่คืนค่าเลย. เบราว์เซอร์จะหมุนต่อไป, IIS ไม่บันทึกอะไร, และส่วนอื่นของเว็บไซต์ยังทำงานต่อ, ทำให้ดูเหมือนการแปลงช้าแทนที่จะเป็น deadlock.
กำหนดแอตทริบิวต์ Async="true" ให้กับหน้าและรันการแปลงเป็นงานอะซิงโครนัสของหน้า:
<%@ Page Language="C#" Async="true" CodeBehind="Convert.aspx.cs" Inherits="MyApp.Convert" %>// Web Forms: the @Page directive needs Async="true", and the conversion runs as a page async task.
// Blocking on it instead (.Result, .Wait(), .GetAwaiter().GetResult()) deadlocks the request:
// it never returns, and nothing is logged.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) return;
RegisterAsyncTask(new PageAsyncTask(async ct =>
{
var converter = Doconut.DoconutHost.Services.GetRequiredService<DocumentConverter>();
using (var pdf = await converter.ConvertAsync(
Server.MapPath("~/App_Data/contract.docx"), ConversionTarget.Pdf, ct: ct))
using (var ms = new MemoryStream())
{
if (pdf.CanSeek) pdf.Position = 0;
await pdf.CopyToAsync(ms);
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=contract.pdf");
Response.BinaryWrite(ms.ToArray());
// Context, not HttpContext.Current: after an await the latter can be null.
Context.ApplicationInstance.CompleteRequest();
}
}));
}หากไม่มี Async="true" ในคำสั่งกำหนด @Page, RegisterAsyncTask จะถูกละเลยโดยไม่มีข้อความแจ้ง. หลังจาก await, ให้ใช้ Context ของหน้า; HttpContext.Current อาจเป็น null ในที่นั้น.
รูปแบบเป้าหมาย
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, PSD, เอกสารเว็บ) มีชุดเป้าหมายที่อนุญาตของตนเอง อย่าเขียนค่าคงที่นี้ลงในรายการเป้าหมายของ UI ของคุณ: ?convert=open จะคืนค่า allowedTargets สำหรับไฟล์ที่อัปโหลด และค่านั้นควรเป็นตัวกำหนดให้ตัวเลือก
วิดเจ็ตแบบดรอปอิน
เอ็นด์พอยต์ ?convert=open|run|download ของวิดเจ็ตให้บริการโดย DocImage.axd และ ปิดโดยค่าเริ่มต้น. เปิดใช้งานพวกมันข้างการลงทะเบียนปลั๊กอิน:
Doconut.DoconutHost.Initialize(options =>
{
options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddConverterWidget(widget =>
{
widget.MaxUploadMb = 25;
});
});
// System.Web reads the whole upload before Doconut sees it: keep maxRequestLength (KB) and
// maxAllowedContentLength (bytes) in Web.config above the widget's MaxUploadMb.<div id="doconut-convert"></div>
<script src="/doconut-res/js/doconutConverter.js"></script>
<script>
Doconut.convert('#doconut-convert', { basePath: '/DocImage.axd', maxUploadMb: 25 });
</script>สองสิ่งที่ควรตรวจสอบเมื่อวิดเจ็ตทำงานผิดพลาด:
basePath: '/DocImage.axd'. ค่าเริ่มต้นของวิดเจ็ตคือ/doconutซึ่งเป็นเอ็นด์พอยต์ของ ASP.NET Core ในแพคเกจนี้ เอ็นด์พอยต์คือตัวจัดการDocImage.axdจากWeb.config.- สคริปต์และเอ็นด์พอยต์ทำงานแยกจากกัน. โมดูลทรัพยากรให้บริการ
doconutConverter.jsไม่ว่าจะวิดเจ็ตเปิดใช้งานหรือไม่ หากไม่มีAddConverterWidget()วิดเจ็ตจะโหลด, วาดโซนดรอปและดูเหมือนทำงานถูกต้อง — แต่การกระทำแรกของมันจะตอบกลับเป็น404.
ขีดจำกัดการอัปโหลด
ASP.NET จะอ่านเนื้อหาคำขอทั้งหมดก่อนที่ DocImage.axd จะทำงาน. การอัปโหลดที่เกิน MaxUploadMb แต่ยังอยู่ต่ำกว่าขีดจำกัดของโฮสต์จะได้รับ JSON 413 ของวิดเจ็ต ("ไฟล์มีขนาดใหญ่เกินไป."). การอัปโหลดที่เกินขีดจำกัดของโฮสต์จะถูก IIS ปฏิเสธก่อน โดยแสดงหน้าข้อผิดพลาดที่วิดเจ็ตไม่สามารถอ่านได้. เก็บขีดจำกัดของโฮสต์ทั้งสองใน Web.config ให้เหนือกว่าขีดจำกัดของวิดเจ็ต:
<system.web>
<httpRuntime maxRequestLength="30720" /> <!-- KILOBYTES: 30 MB -->
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="31457280" /> <!-- BYTES: 30 MB -->
</requestFiltering>
</security>
</system.webServer>ปรับแต่งวิดเจ็ต
ตัวเลือกที่ส่งไปยัง Doconut.convert(selector, options):
| ตัวเลือก | ชนิด | ค่าเริ่มต้น | หมายเหตุ |
|---|---|---|---|
basePath | string | /doconut | URL ของเอ็นด์พอยต์. ตั้งค่า '/DocImage.axd' ในแพคเกจนี้ |
resPath | string | /doconut-res | ยอมรับเพื่อความสอดคล้องกับวิดเจ็ต Doconut ตัวอื่น; วิดเจ็ตแปลงรูปแบบไม่สร้าง URL ใด ๆ จากค่านี้ |
maxUploadMb | number | 25 | ตรวจสอบล่วงหน้าที่ฝั่งไคลเอนต์เท่านั้น; เซิร์ฟเวอร์บังคับขีดจำกัดของตนเอง |
licenseUrl | string | null | null | ทำให้ข้อความลายน้ำบนหน้าผลลัพธ์เป็นลิงก์ |
labels | object | {} | แทนที่สตริงภาษาอังกฤษใด ๆ ของวิดเจ็ตที่ต้องการ |
คอลแบ็ก:
| คอลแบ็ก | เรียกเมื่อ | ข้อมูล |
|---|---|---|
onReady() | วิดเจ็ตได้แสดงหน้าจอดรอแล้ว | — |
onSourceLoaded({ token, pages, sourceExt, allowedTargets }) | ?convert=open สำเร็จ | โทเค็นของแหล่ง, จำนวนหน้า, ส่วนขยายของแหล่ง (ไม่มีจุดนำหน้า), เป้าหมายที่อนุญาต |
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target }) | ?convert=run สำเร็จ | การตอบกลับของการรันพร้อมกับ target ที่ร้องขอ |
onDownload({ downloadName, downloadToken }) | ผู้ใช้คลิกดาวน์โหลด | ทำงานพร้อมกับการดาวน์โหลดของเบราว์เซอร์ |
onError({ phase, message }) | คำขอ open หรือ run ล้มเหลว | phase คือ 'open' หรือ 'run'; message คือข้อผิดพลาดจากเซิร์ฟเวอร์ที่ผ่านการทำความสะอาด |
Doconut.convert() คืนค่าอินสแตนซ์ของวิดเจ็ต: reset() จะกลับไปที่หน้าจอดรอ, loadFile(file) เริ่มกระบวนการด้วย File, และ destroy() จะลบวิดเจ็ตออก.
สร้างส่วนหน้าของคุณเอง
วิดเจ็ตเป็นไคลเอนต์สำหรับสัญญา HTTP นี้บน DocImage.axd:
| เส้นทาง | จุดประสงค์ | การตอบสนองสำเร็จ |
|---|---|---|
POST /DocImage.axd?convert=open (multipart, field file) | อัปโหลดและเปิดเอกสารต้นทาง | 200 — { token, pages, sourceExt, allowedTargets } |
POST /DocImage.axd?token=<token>&convert=run&target=<ext> | แปลงต้นทางที่อัปโหลดเป็น target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET /DocImage.axd?convert=download&token=<downloadToken> | สตรีมไฟล์ที่แปลงแล้ว | 200 — ไฟล์, Content-Disposition: attachment |
แหล่งที่อัปโหลดจะถูกเก็บไว้เป็นเวลา 30 นาที; หลังจากนั้น run จะตอบ 404 และไฟล์ต้องเปิดใหม่อีกครั้ง. downloadToken จะมีหน้าต่างเวลา 30 นาทีของตนเองเมื่อการแปลงเสร็จสิ้น. resultToken เป็นโทเค็นผู้ชมทั่วไปที่มีอายุตามช่วงเวลาการใช้งานของผู้ชม.
sourceExt ในการตอบกลับ open จะไม่มีจุดนำหน้า ("docx") — ตรงกันข้ามกับพารามิเตอร์ sourceExtension ของ ConvertAsync.
| เส้นทาง | สถานะ | เมื่อ | เนื้อหา |
|---|---|---|---|
| ใด ๆ | 404 | วิดเจ็ตไม่ได้เปิดใช้งาน (AddConverterWidget() ไม่เคยถูกเรียก) | เฉพาะสถานะ |
| ใด ๆ | 405 | คำสั่ง HTTP ไม่ถูกต้อง (open/run ต้องใช้ POST, download ต้องใช้ GET) | เฉพาะสถานะ |
open | 413 | การอัปโหลดเกิน MaxUploadMb (แต่ไม่เกินขีดจำกัดของ IIS) | { "error": "File is too large." } |
open | 400 | ไม่มีเนื้อหา multipart, ไม่มีไฟล์, หรือประเภทที่ไม่สามารถแปลงได้ | { "error": "..." } |
open | 403 | ประเภทไฟล์ต้องการความสามารถที่ใบอนุญาตไม่ได้ให้ | { "error": "..." } |
run | 400 | โทเค็นรูปแบบไม่ถูกต้อง, target ไม่รู้จัก, หรือ target ไม่อยู่ใน allowedTargets | { "error": "..." } |
run | 404 | การอัปโหลดหมดอายุหรือไม่เคยเปิด | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | การประมวลผลล้มเหลว | { "error": "<sanitized message>" } |
download | 400 / 404 | โทเค็นดาวน์โหลดรูปแบบไม่ถูกต้อง, ไม่รู้จัก, หรือหมดอายุ | เฉพาะสถานะ |
ความเป็นเจ้าของทรัพยากร
ผู้เรียกเป็นเจ้าของ MemoryStream ที่การแปลงคืนค่าและควรทำการ dispose หลังจากคัดลอกหรือส่งคืน (MVC's File(stream, …) จะทำการ dispose ให้คุณ). อย่าสร้างหรือทำการ dispose DocumentConverter ด้วยตนเอง — ตัวสร้างของมันเป็น internal.
การใส่น้ำลาย
| สถานะใบอนุญาต | การเริ่มต้น | ผลลัพธ์การแปลง |
|---|---|---|
ใบอนุญาตผู้ชมแบบชำระเงินที่ให้สิทธิ์ Converter | เริ่ม | สะอาด — watermarked: false |
| ใบอนุญาตชั่วคราว/ทดลองที่ใช้งานอยู่ | เริ่ม | แปลงพร้อมลายน้ำการประเมิน — watermarked: true |
ไม่มีใบอนุญาต, ไฟล์ TRIAL เก่า, หรือใบอนุญาตที่ไม่มี Converter | Application_Start ขว้างข้อยกเว้น; ทุกคำขอตอบด้วย 500 ว่างเปล่า | — |
| ใบอนุญาตชั่วคราว/ทดลองที่หมดอายุ | เริ่ม | แปลงพร้อมลายน้ำการประเมิน — watermarked: true |
การบูรณาการสามารถสร้างและทดสอบจากต้นจนจบด้วยใบอนุญาตการประเมินก่อนการซื้อ — มีเพียงไบต์ผลลัพธ์ที่เปลี่ยนแปลง.
การแก้ไขปัญหา
| อาการ | การตรวจสอบ |
|---|---|
ทุกคำขอตอบด้วย 500 ว่างเปล่าหลังจากเพิ่มปลั๊กอิน | ใบอนุญาตให้สิทธิ์ Converter — บันทึกเหตุการณ์ Windows, แหล่งที่มาของ ASP.NET |
การแก้ไข DocumentConverter ทำให้เกิดข้อยกเว้น | AddPlugin<ConverterPlugin>() อยู่ใน DoconutHost.Initialize |
| การแปลง Web Forms ไม่เคยคืนค่า | หน้าเว็บบล็อกที่ ConvertAsync — ใช้ Async="true" และ RegisterAsyncTask |
| การแปลงสตรีมบอกว่ารูปแบบไม่รองรับ | sourceExtension มีจุดนำหน้า |
วิดเจ็ตโหลดแต่คำขอของมันตอบ 404 | AddConverterWidget() ไม่ได้ถูกเรียก, หรือ basePath ไม่ใช่ '/DocImage.axd' |
| การอัปโหลดขนาดใหญ่แสดงหน้าข้อผิดพลาดของ IIS แทนข้อความของวิดเจ็ต | maxRequestLength / maxAllowedContentLength ต่ำกว่า MaxUploadMb |
| ไม่มี target | ใช้ allowedTargets จาก convert=open |
| การดาวน์โหลดหมดอายุ | ทำซ้ำ convert=open / convert=run; โทเค็นเป็นชั่วคราวโดยเจตนา |
หน้านี้เป็นประโยชน์หรือไม่?