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

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

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

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

powershell
Install-Package Doconut.NETFramework.Converter

เก็บแพคเกจ Converter ให้เป็นเวอร์ชันเดียวกับ Doconut.NETFramework.

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

ทุกปลั๊กอินจะลงทะเบียนด้วยวิธีเดียวกัน: AddPlugin<TPlugin>() ใน DoconutHost.Initialize.

csharp
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 ที่ใดก็ได้ที่คุณต้องการและใช้ซ้ำได้อย่างอิสระ.

csharp
// Resolve DocumentConverter from DoconutHost.Services; 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) จะมาถึงเป็นสตรีมเช่นผลลัพธ์อื่น ๆ ทุกอย่าง.

ในคอนโทรลเลอร์ MVC 5

ทำให้แอคชันเป็นแบบอะซิงโครนัสและ await การแปลง:

csharp
[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" ให้กับหน้าและรันการแปลงเป็นงานอะซิงโครนัสของหน้า:

aspx
<%@ Page Language="C#" Async="true" CodeBehind="Convert.aspx.cs" Inherits="MyApp.Convert" %>
csharp
// 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 ในที่นั้น.

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

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, PSD, เอกสารเว็บ) มีชุดเป้าหมายที่อนุญาตของตนเอง อย่าเขียนค่าคงที่นี้ลงในรายการเป้าหมายของ UI ของคุณ: ?convert=open จะคืนค่า allowedTargets สำหรับไฟล์ที่อัปโหลด และค่านั้นควรเป็นตัวกำหนดให้ตัวเลือก

วิดเจ็ตแบบดรอปอิน

เอ็นด์พอยต์ ?convert=open|run|download ของวิดเจ็ตให้บริการโดย DocImage.axd และ ปิดโดยค่าเริ่มต้น. เปิดใช้งานพวกมันข้างการลงทะเบียนปลั๊กอิน:

csharp
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.
html
<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 ให้เหนือกว่าขีดจำกัดของวิดเจ็ต:

xml
<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):

ตัวเลือกชนิดค่าเริ่มต้นหมายเหตุ
basePathstring/doconutURL ของเอ็นด์พอยต์. ตั้งค่า '/DocImage.axd' ในแพคเกจนี้
resPathstring/doconut-resยอมรับเพื่อความสอดคล้องกับวิดเจ็ต Doconut ตัวอื่น; วิดเจ็ตแปลงรูปแบบไม่สร้าง URL ใด ๆ จากค่านี้
maxUploadMbnumber25ตรวจสอบล่วงหน้าที่ฝั่งไคลเอนต์เท่านั้น; เซิร์ฟเวอร์บังคับขีดจำกัดของตนเอง
licenseUrlstring | nullnullทำให้ข้อความลายน้ำบนหน้าผลลัพธ์เป็นลิงก์
labelsobject{}แทนที่สตริงภาษาอังกฤษใด ๆ ของวิดเจ็ตที่ต้องการ

คอลแบ็ก:

คอลแบ็กเรียกเมื่อข้อมูล
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>แปลงต้นทางที่อัปโหลดเป็น target200 — { 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)เฉพาะสถานะ
open413การอัปโหลดเกิน MaxUploadMb (แต่ไม่เกินขีดจำกัดของ IIS){ "error": "File is too large." }
open400ไม่มีเนื้อหา multipart, ไม่มีไฟล์, หรือประเภทที่ไม่สามารถแปลงได้{ "error": "..." }
open403ประเภทไฟล์ต้องการความสามารถที่ใบอนุญาตไม่ได้ให้{ "error": "..." }
run400โทเค็นรูปแบบไม่ถูกต้อง, target ไม่รู้จัก, หรือ target ไม่อยู่ใน allowedTargets{ "error": "..." }
run404การอัปโหลดหมดอายุหรือไม่เคยเปิด{ "error": "Upload expired — please re-open the file." }
open, run500การประมวลผลล้มเหลว{ "error": "<sanitized message>" }
download400 / 404โทเค็นดาวน์โหลดรูปแบบไม่ถูกต้อง, ไม่รู้จัก, หรือหมดอายุเฉพาะสถานะ

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

ผู้เรียกเป็นเจ้าของ MemoryStream ที่การแปลงคืนค่าและควรทำการ dispose หลังจากคัดลอกหรือส่งคืน (MVC's File(stream, …) จะทำการ dispose ให้คุณ). อย่าสร้างหรือทำการ dispose DocumentConverter ด้วยตนเอง — ตัวสร้างของมันเป็น internal.

การใส่น้ำลาย

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

การบูรณาการสามารถสร้างและทดสอบจากต้นจนจบด้วยใบอนุญาตการประเมินก่อนการซื้อ — มีเพียงไบต์ผลลัพธ์ที่เปลี่ยนแปลง.

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

อาการการตรวจสอบ
ทุกคำขอตอบด้วย 500 ว่างเปล่าหลังจากเพิ่มปลั๊กอินใบอนุญาตให้สิทธิ์ Converter — บันทึกเหตุการณ์ Windows, แหล่งที่มาของ ASP.NET
การแก้ไข DocumentConverter ทำให้เกิดข้อยกเว้นAddPlugin<ConverterPlugin>() อยู่ใน DoconutHost.Initialize
การแปลง Web Forms ไม่เคยคืนค่าหน้าเว็บบล็อกที่ ConvertAsync — ใช้ Async="true" และ RegisterAsyncTask
การแปลงสตรีมบอกว่ารูปแบบไม่รองรับsourceExtension มีจุดนำหน้า
วิดเจ็ตโหลดแต่คำขอของมันตอบ 404AddConverterWidget() ไม่ได้ถูกเรียก, หรือ basePath ไม่ใช่ '/DocImage.axd'
การอัปโหลดขนาดใหญ่แสดงหน้าข้อผิดพลาดของ IIS แทนข้อความของวิดเจ็ตmaxRequestLength / maxAllowedContentLength ต่ำกว่า MaxUploadMb
ไม่มี targetใช้ allowedTargets จาก convert=open
การดาวน์โหลดหมดอายุทำซ้ำ convert=open / convert=run; โทเค็นเป็นชั่วคราวโดยเจตนา

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