Plugin Chuyển Đổi
Chuyển đổi tài liệu sang 24 định dạng mục tiêu
Plugin Converter biến Doconut thành một dịch vụ chuyển đổi tài liệu. Nó cung cấp động cơ phía sau lớp mặt nạ công khai DocumentConverter và — khi chọn — một widget có thể chèn được được phục vụ bởi DocImage.axd, vì vậy bạn có thể chuyển đổi tài liệu từ C#, từ widget, hoặc từ giao diện người dùng mà bạn tự viết.
Cài đặt gói
Install-Package Doconut.NETFramework.ConverterGiữ phiên bản gói Converter đồng nhất với Doconut.NETFramework.
Đăng ký plugin
Mỗi plugin được đăng ký theo cùng một cách: AddPlugin<TPlugin>() trong DoconutHost.Initialize.
Doconut.DoconutHost.Initialize(options =>
{
options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});Nếu không có giấy phép hoạt động nào cấp khả năng
Converter— không có giấy phép, tệpTRIALcũ, hoặc giấy phép không có khả năng này —DoconutHost.Initializesẽ ném ngoại lệ từApplication_Start. Trong System.Web điều này có nghĩa là mỗi yêu cầu trả về một lỗi500trống, và lý do chỉ được ghi trong nhật ký sự kiện Windows (nguồn ASP.NET). Các giấy phép Demo/NFR tạm thời được chấp nhận. Xem Cài Đặt Giấy Phép.
Chuyển đổi từ C#
Mỗi lần chuyển đổi trả về một MemoryStream có thể tìm kiếm và được đặt vị trí tại 0. DocumentConverter không có trạng thái: lấy nó từ DoconutHost.Services bất cứ nơi nào bạn cần và tái sử dụng tự do.
// 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);Hai chi tiết dễ bị nhầm lẫn: sourceExtension trong phiên bản overload của stream phải bao gồm dấu chấm đầu (".xlsx", không phải "xlsx"), nếu không sẽ không được giải quyết. Và mặc dù tên gọi, WordToHtmlAsync trả về Task<Stream>, không phải Task<string> — tài liệu HTML (hình ảnh được nhúng dưới dạng Base64) sẽ đến dưới dạng stream, giống như mọi kết quả khác.
Trong một controller MVC 5
Biến hành động thành bất đồng bộ và await quá trình chuyển đổi:
[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");
}Trong Web Forms: không bao giờ chặn khi chuyển đổi
Một trang Web Forms chạy trên ngữ cảnh yêu cầu đơn luồng. ConvertAsync sẽ tiếp tục trên ngữ cảnh đó khi hoàn thành, vì vậy một trang chờ đồng bộ — .Result, .Wait(), .GetAwaiter().GetResult() — sẽ giữ lại luồng mà quá trình chuyển đổi cần để kết thúc. Yêu cầu sẽ không bao giờ trả về. Trình duyệt vẫn quay vòng, IIS không ghi log gì, và phần còn lại của site vẫn hoạt động, vì vậy nó trông giống như một quá trình chuyển đổi chậm chứ không phải deadlock.
Đánh dấu trang với Async="true" và chạy quá trình chuyển đổi như một tác vụ bất đồng bộ của trang:
<%@ 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();
}
}));
}Nếu không có Async="true" trong chỉ thị @Page, RegisterAsyncTask sẽ bị bỏ qua một cách im lặng. Sau khi await, hãy sử dụng Context của trang; HttpContext.Current có thể là null ở đó.
Định dạng mục tiêu
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, WebpKhông phải mọi nguồn đều chuyển đổi được sang mọi đích: mỗi họ định dạng nguồn (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project, PSD, web document) có bộ đích cho phép riêng. Đừng hardcode enum này làm danh sách đích cho UI của bạn: ?convert=open trả về allowedTargets cho tệp đã tải lên, và đó là những gì nên điều khiển bộ chọn.
Widget nhúng
Các endpoint ?convert=open|run|download của widget được phục vụ bởi DocImage.axd và mặc định là tắt. Kích hoạt chúng bên cạnh việc đăng ký plugin:
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>Hai điều cần kiểm tra khi widget không hoạt động đúng:
basePath: '/DocImage.axd'. Đường dẫn mặc định của widget là/doconut, là endpoint của ASP.NET Core. Trong gói này, các endpoint là trình xử lýDocImage.axdtừWeb.config.- Script và các endpoint hoạt động độc lập. Module tài nguyên phục vụ
doconutConverter.jsbất kể widget có được bật hay không. Nếu không gọiAddConverterWidget(), widget vẫn tải, vẽ vùng thả, và trông hoàn toàn đúng — nhưng hành động đầu tiên của nó trả về404.
Giới hạn tải lên
ASP.NET đọc toàn bộ thân yêu cầu trước khi DocImage.axd chạy. Một tải lên vượt quá MaxUploadMb nhưng dưới giới hạn của máy chủ sẽ nhận JSON 413 của widget ("File is too large."). Một tải lên vượt quá giới hạn máy chủ sẽ bị IIS từ chối trước, với trang lỗi mà widget không thể đọc được. Giữ cả hai giới hạn máy chủ trong Web.config phía trên giới hạn của widget:
<system.web>
<httpRuntime maxRequestLength="30720" /> <!-- KILOBYTES: 30 MB -->
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="31457280" /> <!-- BYTES: 30 MB -->
</requestFiltering>
</security>
</system.webServer>Tùy chỉnh widget
Các tùy chọn được truyền vào Doconut.convert(selector, options):
| Tùy chọn | Kiểu | Mặc định | Ghi chú |
|---|---|---|---|
basePath | string | /doconut | Địa chỉ endpoint. Đặt '/DocImage.axd' cho gói này |
resPath | string | /doconut-res | Được chấp nhận để đồng nhất với các widget Doconut khác; widget chuyển đổi không xây dựng URL nào từ nó |
maxUploadMb | number | 25 | Chỉ kiểm tra trước phía client; server sẽ áp dụng giới hạn riêng |
licenseUrl | string | null | null | Biến thông báo watermark trên màn hình kết quả thành một liên kết |
labels | object | {} | Ghi đè bất kỳ chuỗi tiếng Anh nào của widget |
Hàm gọi lại:
| Hàm gọi lại | Khi nào được kích hoạt | Dữ liệu |
|---|---|---|
onReady() | Widget đã hiển thị màn hình thả | — |
onSourceLoaded({ token, pages, sourceExt, allowedTargets }) | ?convert=open thành công | Token nguồn, số trang, phần mở rộng nguồn (không có dấu chấm), các đích cho phép |
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target }) | ?convert=run thành công | Phản hồi chạy cộng với target được yêu cầu |
onDownload({ downloadName, downloadToken }) | Người dùng nhấn Tải xuống | Kích hoạt cùng với việc tải xuống của trình duyệt |
onError({ phase, message }) | Yêu cầu mở hoặc chạy thất bại | phase là 'open' hoặc 'run'; message là lỗi máy chủ đã được làm sạch |
Doconut.convert() trả về thể hiện của widget: reset() quay lại màn hình thả, loadFile(file) bắt đầu quy trình với một File, và destroy() loại bỏ nó.
Xây dựng giao diện phía trước của bạn
Widget là một client cho hợp đồng HTTP này trên DocImage.axd:
| Đường dẫn | Mục đích | Phản hồi thành công |
|---|---|---|
POST /DocImage.axd?convert=open (multipart, trường file) | Tải lên và mở tài liệu nguồn | 200 — { token, pages, sourceExt, allowedTargets } |
POST /DocImage.axd?token=<token>&convert=run&target=<ext> | Chuyển đổi nguồn đã tải lên sang target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET /DocImage.axd?convert=download&token=<downloadToken> | Phát luồng tệp đã chuyển đổi | 200 — tệp, Content-Disposition: attachment |
Các nguồn đã tải lên được giữ trong 30 phút; sau thời gian đó, run trả về 404 và tệp phải được mở lại. downloadToken có thời gian 30 phút riêng khi quá trình chuyển đổi hoàn tất. resultToken là một token xem thông thường, kéo dài suốt thời gian phiên xem.
sourceExt trong phản hồi open không có dấu chấm đầu ("docx") — ngược lại với tham số sourceExtension của ConvertAsync.
| Đường dẫn | Trạng thái | Khi | Nội dung |
|---|---|---|---|
| bất kỳ | 404 | Widget không được bật (AddConverterWidget() chưa bao giờ được gọi) | chỉ trạng thái |
| bất kỳ | 405 | Phương thức sai (open/run yêu cầu POST, download yêu cầu GET) | chỉ trạng thái |
open | 413 | Tải lên vượt quá MaxUploadMb (nhưng không vượt quá giới hạn IIS) | { "error": "File is too large." } |
open | 400 | Không có body multipart, không có file, hoặc loại không thể chuyển đổi | { "error": "..." } |
open | 403 | Loại file yêu cầu một khả năng mà giấy phép không cấp | { "error": "..." } |
run | 400 | Token sai dạng, target không xác định, hoặc target không nằm trong allowedTargets | { "error": "..." } |
run | 404 | Tải lên đã hết hạn hoặc chưa bao giờ được mở | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | Xử lý thất bại | { "error": "<sanitized message>" } |
download | 400 / 404 | Token tải xuống sai dạng, không tồn tại hoặc đã hết hạn | chỉ trạng thái |
Quyền sở hữu tài nguyên
Người gọi sở hữu MemoryStream mà quá trình chuyển đổi trả về và nên giải phóng nó sau khi sao chép hoặc trả về (MVC's File(stream, …) sẽ giải phóng cho bạn). Không tự tạo hoặc giải phóng DocumentConverter — hàm khởi tạo của nó là nội bộ.
Đánh dấu nước
| Trạng thái giấy phép | Khởi động | Kết quả chuyển đổi |
|---|---|---|
Giấy phép xem trả phí cho phép Converter | Bắt đầu | Sạch — watermarked: false |
| Giấy phép Tạm thời/Demo đang hoạt động | Bắt đầu | Chuyển đổi, có dấu nước đánh giá — watermarked: true |
Không có giấy phép, tệp TRIAL cũ, hoặc giấy phép không có Converter | Application_Start ném lỗi; mọi yêu cầu trả về 500 trống | — |
| Giấy phép Tạm thời/Demo đã hết hạn | Bắt đầu | Chuyển đổi, có dấu nước đánh giá — watermarked: true |
Một tích hợp có thể được xây dựng và kiểm thử toàn diện trên giấy phép đánh giá trước khi mua — chỉ có các byte đầu ra thay đổi.
Khắc phục sự cố
| Triệu chứng | Kiểm tra |
|---|---|
Mọi yêu cầu trả về 500 trống sau khi thêm plugin | Giấy phép cho phép Converter — kiểm tra nhật ký sự kiện Windows, mã nguồn ASP.NET |
Giải quyết DocumentConverter ném lỗi | AddPlugin<ConverterPlugin>() nằm trong DoconutHost.Initialize |
| Quá trình chuyển đổi Web Forms không bao giờ trả về | Trang bị chặn ở ConvertAsync — sử dụng Async="true" và RegisterAsyncTask |
| Chuyển đổi luồng báo định dạng không được hỗ trợ | sourceExtension có dấu chấm đầu |
Widget tải lên nhưng các yêu cầu trả về 404 | AddConverterWidget() chưa được gọi, hoặc basePath không phải là '/DocImage.axd' |
| Tải lên lớn hiển thị trang lỗi IIS thay vì thông báo của widget | maxRequestLength / maxAllowedContentLength thấp hơn MaxUploadMb |
| Thiếu mục tiêu | Sử dụng allowedTargets từ convert=open |
| Tải xuống đã hết hạn | Lặp lại convert=open / convert=run; các token là tạm thời theo mục đích |
Trang này có hữu ích không?