افزونه مبدل

سندها را به ۲۴ قالب هدف تبدیل کنید

افزونه مبدل Doconut را به یک سرویس تبدیل سند تبدیل می‌کند. این افزونه موتور پشت واسط عمومی DocumentConverter را فراهم می‌کند و — به صورت اختیاری — یک ویجت آماده با قرارداد HTTP خود دارد، به طوری که می‌توانید اسناد را از C#، از ویجت، یا از یک فرانت‌اند که خودتان می‌نویسید، تبدیل کنید.

نصب بسته

آخرین نسخه پایدار افزونه مبدل را نصب کنید:

bash
dotnet add package Doconut.NET8.Converter

برای قفل کردن افزونه به نسخه جاری ۲۶.۷.۰، نسخه را به‌صورت جداگانه پاس دهید:

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

بسته مبدل را با همان نسخه‌ی Doconut.NET8 نگه دارید. شناسه بسته Doconut.NET8.Converter است؛ .26.7.0 فقط در نام فایل دانلود شده‌ی .nupkg ظاهر می‌شود.

ثبت افزونه

هیچ روش AddConverter() وجود ندارد — مدل افزونه‌های Doconut یکنواخت است. هر افزونه‌ای، از جمله مبدل، به همان روش ثبت می‌شود: داخل AddDoconut()، AddPlugin<TPlugin>() را فراخوانی کنید. 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 پذیرفته می‌شوند؛ پس از انقضای تقویمی آن‌ها، تبدیل همچنان با خروجی دارای واترمارک در دسترس است. هیچ لایه رایگان ساکتی وجود ندارد. برای نحوه بارگذاری لایسنس‌ها، به License Setup مراجعه کنید.

تبدیل از C#

هر تبدیل یک MemoryStream قابل جستجو که در موقعیت ۰ قرار دارد، برمی‌گرداند که بلافاصله آماده خواندن یا کپی شدن است. DocumentConverter را از DI در هر جایی که نیاز دارید حل کنید — این شیء به‌صورت بدون حالت طراحی شده است، بنابراین یک نمونه‌ی واحد می‌تواند به‌صورت ایمن در درخواست‌های مختلف دوباره استفاده شود.

csharp
// DocumentConverter را تزریق کنید؛ سازندهٔ آن داخلی است، بنابراین هرگز `new` آن را انجام ندهید.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);
csharp
// sourceExtension شامل نقطهٔ پیشرو است. password برابر null است مگر اینکه سند محافظت شده باشد.
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، سند وب) را به مجموعه ثابت هدف‌های مجاز خود نگاشت می‌کند. این enum را به‌عنوان لیست هدف‌های UI خود به‌صورت ثابت کدنویسی نکنید: ?convert=open مقدار واقعی allowedTargets را برای فایلی که تازه بارگذاری شده است برمی‌گرداند و این باید منبع انتخاب‌کننده باشد.

ویجت Drop‑in

نقطه‌های انتهایی ?convert=open|run|download ویجت به‌صورت انتخابی هستند و به‌طور پیش‌فرض غیرفعال‌اند — به‌صورت پیش‌فرض ایمن. آنها را در سمت سرور فعال کنید، به‌همراه ثبت‌نام افزونه:

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/doconutمسیر پایه برای نقطه‌های انتهایی ?convert=؛ باید با شاخه ASP.NET که در آن UseDoconut() واقعاً سوار شده است مطابقت داشته باشد (معمولاً از طریق MiddlewarePath هماهنگ می‌شود)
resPathstring/doconut-resبرای سازگاری پیکربندی با سایر ویجت‌های Doconut پذیرفته شده است؛ ویجت مبدل در حال حاضر هیچ URL‌ای از آن نمی‌سازد
maxUploadMbnumber25فقط بررسی پیش‌نگار در سمت کلاینت — قبل از بارگذاری، فایل بزرگ‌تری را رد می‌کند. سرور به‌صورت مستقل سقف خود را اعمال می‌کند و اگر تجاوز شود، پاسخ 413 می‌دهد
licenseUrlstring | nullnullهنگامی که تنظیم شود، اعلان واترمارک در صفحهٔ نتیجه را به لینکی به این URL تبدیل می‌کند
labelsobject{}هر زیرمجموعه‌ای از رشته‌های پیش‌فرض انگلیسی ویجت (متن کشیدن، دکمه‌ها، اعلان‌های aria‑live، پیام‌های خطا) را بازنویسی می‌کند

بازخوانی‌ها:

بازخوانیزمان اجراداده
onReady()ویجت صفحهٔ بیکار/کشیدن خود را رندر کرده است—
onSourceLoaded({ token, pages, sourceExt, allowedTargets })?convert=open موفق می‌شودتوکن نشست منبع، تعداد صفحات، پسوند منبع (بدون نقطهٔ پیش‌رو)، لیست هدف‌های مجاز
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target })?convert=run موفق می‌شودهمان فیلدها همانند پاسخ اجرا، به‌اضافهٔ target درخواست‌شده
onDownload({ downloadName, downloadToken })کاربر بر لینک دانلود کلیک می‌کندبه‌همراه دانلود بومی مرورگر اجرا می‌شود — آن را رهگیری یا جایگزین نمی‌کند
onError({ phase, message })یک درخواست باز یا اجرا شکست می‌خوردphase برابر است با 'open' یا 'run'؛ message خطای سرور تمیزشده است (یا پیام سمت کلاینت برای بررسی پیش‌نگار اندازه بارگذاری)

Doconut.convert() نمونهٔ ویجت را خود باز می‌گرداند — آن را نگه دارید تا ویجت را به‌صورت برنامه‌نویسی کنترل کنید:

javascript
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset();         // بازگشت به صفحه idle/drop؛ onReady دوباره فراخوانی نمی‌شود
conv.loadFile(file);  // جریان را با یک شیء File شروع می‌کند؛ no‑op مگر اینکه در حال حاضر idle باشد
conv.destroy();       // listenerها را حذف می‌کند، mount را خالی می‌کند؛ پس از این نمونه قابل استفاده نیست

ساخت رابط کاربری خودتان

ویجت صرفاً یک کلاینت برای این قرارداد HTTP است — می‌توانید رابط کاربری خود را مستقیماً بر پایهٔ آن بسازید تا تجربهٔ کاربری متفاوتی داشته باشید. هر سه مسیر زیر شاخهٔ 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

بایت‌های منبع بارگذاری‌شده به‌صورت سروری با TTL 30 دقیقه‌ای ذخیره می‌شوند؛ پس از پایان این بازه، run پاسخ 404 می‌دهد و فایل باید دوباره باز شود. نتیجهٔ تبدیل‌شده در همان مخزن زندگی می‌کند — downloadToken پس از تکمیل تبدیل، بازهٔ تازهٔ 30 دقیقه‌ای خود را دریافت می‌کند — در حالی که resultToken یک توکن نشست معمولی ویور است که طول عمر آن مطابق کش نشست ویور است، مستقل از مخزن.

sourceExt در پاسخ open نقطهٔ پیش‌رو ندارد (مثلاً "docx") — بر خلاف قرارداد پارامتر sourceExtension در DocumentConverter.ConvertAsync که نیاز به نقطه دارد.

حالت‌های شکست، گروه‌بندی‌شده بر حسب مسیر:

مسیروضعیتزمانبدنه
هر404ویجت فعال نیست (AddConverterWidget() هرگز فراخوانی نشده است) — قبل از ارسال هر یک از سه مسیر بررسی می‌شودفقط وضعیت
هر405روش HTTP نادرست (open/run به POST نیاز دارند؛ download به GET نیاز دارد)فقط وضعیت
open413فایل بارگذاری‌شده از MaxUploadMb تجاوز می‌کند{ "error": "File is too large." }
open400بدنهٔ multipart وجود ندارد، فایل نیست، یا پسوند منبعی که قابل تبدیل نیست{ "error": "..." }
run400توکن خراب (نه 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 دقیقه) یا توکن هرگز باز نشده است{ "error": "Upload expired — please re-open the file." }
open, run500پردازش به‌صورت داخلی شکست خورده است{ "error": "<sanitized message>" } — به همان شیوه سایر مسیرهای خطای Doconut تمیز شده؛ هرگز نام‌های داخلی موتور را فاش نمی‌کند
download400توکن خراب (نه GUID)فقط وضعیت
download404توکن دانلود ناشناخته یا منقضی شدهفقط وضعیت

مالکیت منبع

مبدل یک MemoryStream قابل جستجو که در صفر موقعیت دارد برمی‌گرداند. صدا کننده مالک این جریان است و باید پس از کپی یا بازگرداندن محتویات آن، آن را آزاد کند. سرویس DocumentConverter خود بدون حالت است و از تزریق وابستگی حل می‌شود؛ سرویس را به‌صورت دستی ساخت یا آزاد نکنید.

برای ویجت وب، مخازن بارگذاری و دانلود TTLهای مستقل 30‑دقیقه‌ای دارند. یک resultToken نمایشگر به‌جای آن، طول عمر جلسه نمایشگر را دنبال می‌کند. بستن نتیجهٔ نمایشگر مخزن دانلود هنوز معتبر را حذف نمی‌کند، و بازنشانی ویجت مرورگر هیچ‌یک از TTLها را تمدید نمی‌کند.

عیب‌یابی

علائمبررسی
شکست در حل DocumentConverterثبت ConverterPlugin داخل AddDoconut() رخ داد
برنامه در هنگام راه‌اندازی شکست می‌خوردمجوز بارگذاری‌شده Converter را اعطا می‌کند
تبدیل جریان می‌گوید قالب پشتیبانی نمی‌شودsourceExtension شامل نقطهٔ پیش‌رو است
جاوااسکریپت ویجت بارگذاری می‌شود اما درخواست‌ها 404 برمی‌گردانندAddConverterWidget() فراخوانی نشد
درخواست‌های ویجت از URL اشتباه استفاده می‌کنندbasePath با شاخه‌ای که UseDoconut() در آن نگاشته شده مطابقت دارد
هدف موجود نیستاز allowedTargets که توسط convert=open برگردانده شده استفاده کنید؛ هر منبع همهٔ هدف‌های enum را پشتیبانی نمی‌کند
دانلود منقضی شدهدوباره convert=open/convert=run را انجام دهید؛ توکن‌های مخزن عمداً موقت هستند

واترمارک‌گذاری

با ثبت ConverterPlugin، مجوز میزبان در یکی از سه وضعیت زیر است:

وضعیت مجوزدروازهٔ راه‌اندازیخروجی تبدیل
مجوز نمایشگر پرداخت‌شده که Converter را اعطا می‌کند، در دورهٔ اعتبار خودعبور می‌کندتمیز — watermarked: false
مجوز ارزیابی فعال (دمو/NFR)عبور می‌کندبا موفقیت تبدیل می‌شود، با واترمارک ارزیابی — watermarked: true مهر می‌شود
بدون مجوز، فایل قدیمی TRIAL، یا مجوز غیر موقت که Converter را اعطا نمی‌کندبرنامه هرگز شروع نمی‌شود — دروازهٔ راه‌اندازی که در بالا توضیح داده شد استثنا می‌اندازد—
مجوز موقت/دموی منقضی‌شدهثبت پس از انقضا باقی می‌ماندبا واترمارک ارزیابی تبدیل می‌شود — watermarked: true

هر دو مسیر فراخوانی پرچم را از همان قانون محاسبه می‌کنند: واسط C# DocumentConverter آن را به‌صورت داخلی از وضعیت IsViewerLicensed و IsTemporary مجوز استخراج می‌کند، و هندلر ?convert=run ویجت بررسی معادل (IsViewerLicensed && !IsTrial && !IsTemporary) را انجام می‌دهد تا فیلد watermarked را که برمی‌گرداند پر کند. یک یکپارچه‌سازی می‌تواند بر روی یک مجوز ارزیابی قبل از خرید ساخته و به‌صورت سرتاسری تست شود — فقط بایت‌های خروجی تغییر می‌کنند.

آیا این صفحه مفید بود؟