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 giao diện công khai DocumentConverter, và — khi bật tùy chọn — một widget có thể chèn sẵn với hợp đồng HTTP riêng, cho phép bạn 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
Cài đặt plugin Converter mới nhất và ổn định:
dotnet add package Doconut.NET8.ConverterĐể cố định plugin vào phiên bản 26.7.0 hiện tại, truyền phiên bản riêng biệt:
dotnet add package Doconut.NET8.Converter --version 26.7.0Giữ gói Converter ở cùng phiên bản với Doconut.NET8. ID gói là
Doconut.NET8.Converter; .26.7.0 chỉ xuất hiện trong tên tệp .nupkg đã tải xuống.
Đăng Ký Plugin
Không có phương thức AddConverter() — mô hình plugin của Doconut là đồng nhất. Mỗi plugin, bao gồm Converter, đều được đăng ký theo cùng một cách: gọi AddPlugin<TPlugin>() bên trong AddDoconut(). ConverterPlugin được cung cấp trong gói NuGet riêng, Doconut.NET8.Converter, được cài đặt cùng với gói viewer cơ bản.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});Lệnh này sẽ ném lỗi khi khởi động nếu thiếu giấy phép, tệp
TRIALcũ, hoặc giấy phép không tạm thời không cấp quyềnConverter— mộtInvalidOperationExceptionđược phát sinh từ bên trongAddDoconut(), trước khi ứng dụng phục vụ các yêu cầu. Các đăng ký Demo/NFR tạm thời được chấp nhận; sau khi hết hạn lịch, việc chuyển đổi vẫn khả dụng nhưng kết quả có dấu watermark. Không có cấp miễn phí ẩn. Xem Cài Đặt Giấy Phép để biết cách tải 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ị trí ở 0, sẵn sàng để đọc hoặc sao chép ngay lập tức. Lấy DocumentConverter từ DI bất cứ nơi nào bạn cần — nó không có trạng thái theo thiết kế, vì vậy một thể hiện duy nhất có thể tái sử dụng an toàn giữa các yêu cầu.
// 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);Hai chi tiết dễ bị nhầm lẫn: sourceExtension trong overload cho stream phải bao gồm dấu chấm đầu (".xlsx", không phải "xlsx") — bộ chuyển đổi sẽ so sánh nó với danh mục định dạng và một phần mở rộng không có dấu chấm 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> — bạn nhận được tài liệu HTML (hình ảnh được nhúng dưới dạng Base64) dưới dạng stream, giống như mọi kết quả chuyển đổi khác.
Định Dạng Đích
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 có thể chuyển sang mọi đích — plugin ánh xạ mỗi họ định dạng nguồn (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project/Task, PSD, tài liệu web) tới một tập hợp cố định các đích được phép. Đừng hardcode enum này làm danh sách đích cho UI của bạn: ?convert=open trả về allowedTargets thực tế cho tệp vừa được tải lên, và đó là dữ liệu nên dùng để tạo bộ chọn.
Widget Chèn Sẵn
Các endpoint ?convert=open|run|download của widget là tùy chọn và mặc định bị vô hiệu hoá — bảo mật theo mặc định. Kích hoạt chúng phía máy chủ, cùng với việc đăng ký plugin:
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>Nếu không có AddConverterWidget(), ba endpoint ?convert= sẽ trả về 404 — nhưng tệp JS vẫn được phục vụ bất kể (đó là tài nguyên tĩnh nhúng đơn giản; chỉ các endpoint mà nó giao tiếp mới bị kiểm soát). AddConverterWidget() vẫn yêu cầu plugin Converter đã được đăng ký và một giấy phép cấp quyền Converter — nó không tự mình cấp quyền chuyển đổi.
Tùy Chỉnh Widget
Các tùy chọn khởi tạo được truyền vào Doconut.convert(selector, options):
| Tùy chọn | Kiểu | Mặc định | Ghi chú |
|---|---|---|---|
basePath | string | /doconut | Đường dẫn cơ sở cho các endpoint ?convert=; phải khớp với nhánh ASP.NET nơi UseDoconut() thực sự được gắn (thông thường được điều phối qua MiddlewarePath). |
resPath | string | /doconut-res | Được chấp nhận để đồng nhất cấu hình với các widget Doconut khác; hiện tại widget chuyển đổi không xây dựng URL nào từ nó. |
maxUploadMb | number | 25 | Kiểm tra trước phía client — từ chối tệp quá lớn trước khi tải lên. Máy chủ áp dụng giới hạn riêng và trả về 413 nếu vượt quá. |
licenseUrl | string | null | null | Khi được đặt, chuyển thông báo watermark trên màn hình kết quả thành một liên kết tới URL này. |
labels | object | {} | Ghi đè bất kỳ tập con nào của các chuỗi mặc định tiếng Anh của widget (văn bản thả, nút, thông báo aria-live, thông báo lỗi). |
Các Callback:
| Callback | Khi nào được kích hoạt | Dữ liệu |
|---|---|---|
onReady() | Widget đã hiển thị màn hình chờ/đổ | — |
onSourceLoaded({ token, pages, sourceExt, allowedTargets }) | ?convert=open thành công | token phiên nguồn, số trang, phần mở rộng nguồn (không có dấu chấm), danh sách đích cho phép |
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target }) | ?convert=run thành công | các trường giống như phản hồi run, cộng thêm target được yêu cầu |
onDownload({ downloadName, downloadToken }) | Người dùng nhấn liên kết Tải xuống | kích hoạt cùng với tải xuống gốc của trình duyệt — không can thiệp hay thay thế |
onError({ phase, message }) | Yêu cầu open hoặc run thất bại | phase là 'open' hoặc 'run'; message là lỗi đã được làm sạch từ server (hoặc thông báo client cho kiểm tra kích thước upload) |
Doconut.convert() trả về chính thể hiện widget — giữ nó lại để điều khiển widget bằng mã:
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset(); // back to the idle/drop screen; does not re-fire onReady
conv.loadFile(file); // starts the flow with a File object; no-op unless currently idle
conv.destroy(); // removes listeners, empties the mount; the instance is unusable after thisXây Dựng Giao Diện Người Dùng Riêng
Widget chỉ là một client cho hợp đồng HTTP này — xây dựng giao diện người dùng riêng của bạn trực tiếp dựa trên nó để có trải nghiệm khác. Ba route đều nằm dưới nhánh ASP.NET nơi UseDoconut() được gắn (thông thường là /doconut):
| Route | Mục đích | Phản hồi thành công |
|---|---|---|
POST ?convert=open (multipart, field file) | Tải lên và mở tài liệu nguồn để xem trước | 200 — { token, pages, sourceExt, allowedTargets } |
POST ?token=<token>&convert=run&target=<ext> | Chuyển đổi nguồn đã lưu sang target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET ?convert=download&token=<downloadToken> | Phát luồng tệp đã chuyển đổi | 200 — file bytes, Content-Disposition: attachment, Cache-Control: no-store |
Byte nguồn đã tải lên được lưu tạm phía máy chủ với thời gian sống (TTL) 30 phút; khi thời gian này hết, run trả về 404 và tệp phải được mở lại. Kết quả chuyển đổi nằm trong cùng kho lưu — downloadToken nhận một cửa sổ 30 phút mới khi chuyển đổi hoàn tất — trong khi resultToken là một token phiên viewer thông thường, thời gian sống của nó theo bộ nhớ cache phiên của viewer, độc lập với kho lưu.
sourceExt trong phản hồi open không có dấu chấm đầu (ví dụ: "docx") — ngược lại với quy ước của tham số sourceExtension trên DocumentConverter.ConvertAsync, yêu cầu có dấu chấm.
Các Trường Hợp Lỗi, Nhóm Theo Route
| Route | Trạng thái | Khi nào | Nội dung |
|---|---|---|---|
| any | 404 | Widget không được bật (AddConverterWidget() chưa được gọi) — được kiểm tra trước khi bất kỳ route nào trong ba route được xử lý | status only |
| any | 405 | Wrong HTTP verb (open/run require POST; download requires GET) | status only |
open | 413 | Uploaded file exceeds MaxUploadMb | { "error": "File is too large." } |
open | 400 | No multipart body, no file, or a source extension that can't be converted | { "error": "..." } |
run | 400 | Malformed token (not a GUID), or a target that doesn't parse to a ConversionTarget | { "error": "Invalid token." } / { "error": "Unknown target format." }` |
run | 400 | target isn't in the source's allowedTargets | { "error": "That target format is not available for this file." } |
run | 404 | The stashed upload has expired (30-minute TTL) or the token was never opened | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | Processing failed internally | { "error": "<sanitized message>" } — được làm sạch theo cùng cách như mọi đường lỗi khác của Doconut; không bao giờ rò rỉ tên engine nội bộ |
download | 400 | Malformed token (not a GUID) | status only |
download | 404 | Unknown or expired download token | status only |
Quyền Sở Hữu Tài Nguyên
Converter trả về một MemoryStream có thể tìm kiếm, vị trí ở 0. Người gọi sở hữu stream này và nên giải phóng nó sau khi sao chép hoặc trả về nội dung. Dịch vụ DocumentConverter tự nó không có trạng thái và được lấy từ dependency injection; không tự tạo hoặc giải phóng dịch vụ này một cách thủ công.
Đối với widget web, các kho lưu upload và download có TTL độc lập 30 phút. resultToken của viewer tuân theo thời gian sống của phiên viewer. Đóng kết quả viewer không xóa kho lưu download còn hiệu lực, và việc đặt lại widget trong trình duyệt không kéo dài bất kỳ TTL nào.
Khắc Phục Sự Cố
| Triệu chứng | Kiểm tra |
|---|---|
Không thể giải quyết DocumentConverter | Đăng ký ConverterPlugin đã được thực hiện bên trong AddDoconut() |
| Ứng dụng gặp lỗi khi khởi động | Giấy phép đã tải cho phép Converter |
| Chuyển đổi stream báo định dạng không được hỗ trợ | sourceExtension bao gồm dấu chấm đầu |
| JavaScript của widget tải nhưng các yêu cầu trả về 404 | AddConverterWidget() chưa được gọi |
| Các yêu cầu của widget sử dụng URL sai | basePath khớp với nhánh nơi UseDoconut() được ánh xạ |
| Đích bị thiếu | Sử dụng allowedTargets trả về bởi convert=open; không phải mọi nguồn đều hỗ trợ mọi enum target |
| Tải xuống đã hết hạn | Lặp lại convert=open/convert=run; token lưu tạm có thời gian tồn tại cố định |
Đánh Dấu Watermark
Khi ConverterPlugin đã được đăng ký, giấy phép của host nằm trong một trong ba trạng thái:
| Trạng thái giấy phép | Cổng khởi động | Kết quả chuyển đổi |
|---|---|---|
Giấy phép viewer trả phí cấp Converter, trong thời gian hiệu lực | Đạt | Sạch — watermarked: false |
| Giấy phép đánh giá (demo/NFR) đang hoạt động | Đạt | Chuyển đổi thành công, có dấu watermark đánh giá — watermarked: true |
Không có giấy phép, tệp TRIAL cũ, hoặc giấy phép không tạm thời không cấp Converter | Ứng dụng không bao giờ khởi động — cổng khởi động mô tả ở trên ném lỗi | — |
| Giấy phép tạm thời/Demo đã hết hạn | Đăng ký vẫn tồn tại sau khi hết hạn | Chuyển đổi có watermark đánh giá — watermarked: true |
Cả hai đường gọi đều tính cờ này dựa trên cùng một quy tắc: giao diện C# DocumentConverter suy ra nội bộ từ trạng thái IsViewerLicensed và IsTemporary của giấy phép, và bộ xử lý ?convert=run của widget thực hiện kiểm tra tương đương (IsViewerLicensed && !IsTrial && !IsTemporary) để điền trường watermarked mà nó trả về. Một tích hợp có thể được xây dựng và kiểm thử end‑to‑end trên giấy phép đánh giá trước khi mua — chỉ có byte đầu ra thay đổi.
Trang này có hữu ích không?