ملحق المحول
تحويل المستندات إلى 24 تنسيقًا مستهدفًا
يحوِّل ملحق المحول Doconut إلى خدمة تحويل المستندات. يساهم بالمحرك وراء الواجهة العامة DocumentConverter، و— عند الاختيار — عنصر واجهة مستخدم جاهز مع عقد HTTP الخاص به، بحيث يمكنك تحويل المستندات من C#، أو من العنصر، أو من الواجهة الأمامية التي تكتبها بنفسك.
تثبيت الحزمة
ثبت أحدث نسخة مستقرة من ملحق المحول:
dotnet add package Doconut.NET6.Converterلتثبيت الملحق على الإصدار الحالي 26.7.0، مرّر الإصدار بشكل منفصل:
dotnet add package Doconut.NET6.Converter --version 26.7.0احتفظ بحزمة المحول بنفس الإصدار كما هو الحال مع Doconut.NET6. معرف الحزمة هو
Doconut.NET6.Converter؛ يظهر .26.7.0 فقط في اسم الملف .nupkg الذي تم تنزيله.
تسجيل الملحق
لا توجد طريقة AddConverter() — نموذج ملحقات Doconut موحد. كل ملحق، بما في ذلك المحول، يُسجَّل بنفس الطريقة: استدعِ AddPlugin<TPlugin>() داخل AddDoconut(). ConverterPlugin يأتي في حزمة NuGet الخاصة به، Doconut.NET6.Converter، مثبتًا جنبًا إلى جنب مع حزمة عارض الأساس.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});يثير هذا الاستدعاء خطأً عند بدء التشغيل بسبب ترخيص مفقود، أو ملف
TRIALقديم، أو ترخيص غير مؤقت لا يمنح القدرة علىConverter— وهوInvalidOperationExceptionيُرفع من داخلAddDoconut()، قبل أن يبدأ التطبيق في خدمة الطلبات. تُقبل تسجيلات Demo/NFR المؤقتة؛ بعد انتهاء صلاحيتها، يظل التحويل متاحًا مع مخرجات مائية. لا توجد طبقة مجانية صامتة. راجع إعداد الترخيص لمعرفة كيفية تحميل التراخيص.
التحويل من C#
كل عملية تحويل تُعيد MemoryStream قابلًا للبحث موضعه 0، جاهزًا للقراءة أو النسخ فورًا. احصل على DocumentConverter من DI أينما احتجت إليه — فهو غير حالة حسب التصميم، لذا يمكن إعادة استخدام نسخة واحدة بأمان عبر الطلبات.
// قم بحقن DocumentConverter؛ مُنشئه داخلي، لذا لا تقم أبداً بـ `new` له.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);// sourceExtension يتضمن النقطة الأولية. password يكون null ما لم يكن المستند محمياً.
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 في التحميل الزائد للمجرى النقطة الرائدة (".xlsx"، وليس "xlsx") — حيث يطابق المحول ذلك مع كتالوج الصيغ ولن تُحلّ الامتداد المجردة. وعلى الرغم من اسمه، يُعيد WordToHtmlAsync Task<Stream>، وليس Task<string> — تحصل على مستند HTML (الصور مدمجة كـ Base64) كمجرى، كما هو الحال مع كل نتيجة تحويل أخرى.
صيغ الهدف
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، مستند ويب) بمجموعة ثابتة من الأهداف المسموح بها. لا تقم بترميز هذا التعداد صلبًا في قائمة أهداف واجهة المستخدم الخاصة بك: ?convert=open يُعيد allowedTargets الفعلي لأي ملف تم رفعه للتو، وهذا ما ينبغي أن يحدد القائمة المنسدلة.
عنصر واجهة المستخدم القابل للإدراج
نقاط النهاية ?convert=open|run|download للعنصر قابلة للاختيار ومعطلة بشكل افتراضي — آمنة بشكل افتراضي. قم بتمكينها على الخادم، جنبًا إلى جنب مع تسجيل المكوّن الإضافي:
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>بدون AddConverterWidget()، فإن نقاط النهاية الثلاثة ?convert= تجيب بـ 404 — لكن ملف الـ JS نفسه لا يزال يُقدَّم على أي حال (إنه مورد ثابت مضمّن بسيط؛ فقط نقاط النهاية التي يتواصل معها هي المحجوبة). لا يزال AddConverterWidget() يتطلب تسجيل مكوّن Converter وإصدار ترخيص يمنح Converter — لا يمنح حقوق التحويل بمفرده.
تخصيص العنصر
خيارات التهيئة الممررة إلى Doconut.convert(selector, options):
| الخيار | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
basePath | string | /doconut | المسار الأساسي لنقاط النهاية ?convert=؛ يجب أن يتطابق مع فرع ASP.NET حيث يتم تثبيت UseDoconut() فعليًا (عادةً ما يتم التنسيق عبر MiddlewarePath) |
resPath | string | /doconut-res | مقبول لضمان اتساق التكوين مع عناصر Doconut الأخرى؛ عنصر التحويل لا يُنشئ حاليًا أي عنوان URL منه |
maxUploadMb | number | 25 | تحقق مسبق من جانب العميل فقط — يرفض ملفًا كبيرًا جدًا قبل الرفع. يفرض الخادم حدّه الخاص بشكل مستقل ويجيب بـ 413 إذا تم تجاوز الحد |
licenseUrl | string | null | null | عند التعيين، يحول إشعار العلامة المائية على شاشة النتيجة إلى رابط إلى هذا العنوان |
labels | object | {} | يتجاوز أي مجموعة فرعية من السلاسل الافتراضية الإنجليزية للعنصر (نص السحب، الأزرار، إعلانات 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() يُعيد نسخة العنصر نفسها — احتفظ به لتوجيه العنصر برمجيًا:
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset(); // العودة إلى شاشة الخمول/الإسقاط؛ لا يعيد تشغيل onReady
conv.loadFile(file); // يبدأ التدفق باستخدام كائن File؛ لا يفعل شيئًا إلا إذا كان النظام في حالة الخمول
conv.destroy(); // يزيل المستمعين، يفرغ الـ mount؛ الكائن غير قابل للاستخدام بعد ذلكبناء الواجهة الأمامية الخاصة بك
العنصر هو مجرد عميل لهذا العقد HTTP — قم ببناء واجهة أمامية خاصة بك مباشرةً ضده لتجربة مستخدم مختلفة. جميع المسارات الثلاثة تقع تحت فرع ASP.NET حيث يتم تثبيت UseDoconut() (عادةً /doconut):
| المسار | الغرض | استجابة النجاح |
|---|---|---|
POST ?convert=open (multipart, field file) | رفع وفتح مستند مصدر للمعاينة | 200 — { token, pages, sourceExt, allowedTargets } |
POST ?token=<token>&convert=run&target=<ext> | تحويل المصدر المخزن إلى target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET ?convert=download&token=<downloadToken> | بث الملف المحوَّل | 200 — file bytes, Content-Disposition: attachment, Cache-Control: no-store |
يتم تخزين بايتات المصدر المرفوعة على الخادم مع TTL مدته 30 دقيقة؛ بمجرد انتهاء هذه النافذة، يجيب run بـ 404 ويجب إعادة فتح الملف. النتيجة المحوَّلة تعيش في نفس التخزين — يحصل downloadToken على نافذة جديدة مدتها 30 دقيقة عند اكتمال التحويل — بينما resultToken هو رمز جلسة عارض عادي تتبع مدة تخزين جلسة العارض، مستقلًا عن التخزين.
sourceExt في استجابة open لا يحتوي على نقطة أمامية (مثال: "docx") — وهو عكس الاتفاقية للمعامل sourceExtension على DocumentConverter.ConvertAsync، الذي يتطلب واحدة.
أنماط الفشل، مجمّعة حسب المسار:
| المسار | الحالة | متى | المحتوى |
|---|---|---|---|
| any | 404 | العنصر غير مفعّل (AddConverterWidget() لم يُستدعَ أبداً) — يتم التحقق قبل إرسال أي من المسارات الثلاثة | الحالة فقط |
| any | 405 | طريقة HTTP غير صحيحة (open/run تتطلب POST؛ download يتطلب GET) | الحالة فقط |
open | 413 | الملف المرفوع يتجاوز MaxUploadMb | { "error": "File is too large." } |
open | 400 | لا يوجد جسم multipart، لا ملف، أو امتداد مصدر لا يمكن تحويله | { "error": "..." } |
run | 400 | رمز غير صالح (ليس GUID)، أو target لا يمكن تحليله إلى ConversionTarget | { "error": "Invalid token." } / { "error": "Unknown target format." } |
run | 400 | target غير موجود في allowedTargets المصدر | { "error": "That target format is not available for this file." } |
run | 404 | انتهت صلاحية الرفع المخزن (TTL 30 دقيقة) أو لم يتم فتح الرمز | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | فشل المعالجة داخليًا | { "error": "<sanitized message>" } — تم تنقيحه بنفس طريقة كل مسار خطأ آخر في Doconut؛ لا يكشف عن أسماء المحركات الداخلية |
download | 400 | رمز غير صالح (ليس GUID) | الحالة فقط |
download | 404 | رمز تحميل غير معروف أو منتهي الصلاحية | الحالة فقط |
ملكية المورد
المحوّل يُعيد MemoryStream قابل للبحث موضعه عند الصفر. المتصل يملك هذا التدفق ويجب أن يُفرغّه بعد النسخ أو إرجاع محتوياته. خدمة DocumentConverter نفسها لا تحتفظ بحالة ويتم حلّها عبر حقن الاعتماديات؛ لا تقم بإنشاء الخدمة أو إفراغها يدوياً.
بالنسبة لأداة الويب، فإن مخازن الرفع والتحميل لديها فترات صلاحية مستقلة مدتها 30 دقيقة. مشاهد resultToken يتبع بدلاً من ذلك عمر جلسة المشاهد. إغلاق نتيجة المشاهد لا يحذف مخزن التحميل الذي لا يزال صالحًا، وإعادة ضبط أداة المتصفح لا تمدّد أيًا من فترات الصلاحية.
استكشاف الأخطاء وإصلاحها
| العَرَض | الفحص |
|---|---|
فشل حل DocumentConverter | ConverterPlugin تم التسجيل داخل AddDoconut() |
| فشل التطبيق أثناء بدء التشغيل | الرخصة المحمّلة تمنح Converter |
| تحويل التدفق يقول إن الصيغة غير مدعومة | sourceExtension يتضمن النقطة الأولية |
| جافاسكريبت الأداة يُحمّل لكن الطلبات تُعيد 404 | AddConverterWidget() لم يُستدعَ |
| طلبات الأداة تستخدم عنوان URL خاطئ | basePath يطابق الفرع حيث تم تعيين UseDoconut() |
| الهدف مفقود | استخدم allowedTargets الذي أرجعه convert=open؛ ليس كل مصدر يدعم كل هدف تعداد |
| انتهت صلاحية التحميل | أعد convert=open/convert=run؛ رموز المخزن مؤقتة عن قصد |
وضع العلامة المائية
مع تسجيل ConverterPlugin، تكون رخصة المضيف في إحدى ثلاث حالات:
| حالة الرخصة | بوابة بدء التشغيل | مخرجات التحويل |
|---|---|---|
رخصة مشاهد مدفوعة تمنح Converter، ضمن فترة صلاحيتها | تنجح | نظيف — watermarked: false |
| رخصة تقييم نشطة (تجريبية/غير تجارية) | تنجح | يتحول بنجاح، مختومة بعلامة التقييم المائية — watermarked: true |
بدون رخصة، ملف TRIAL قديم، أو رخصة غير مؤقتة لا تمنح Converter | التطبيق لا يبدأ أبداً — بوابة بدء التشغيل المذكورة أعلاه تُطلق استثناء | — |
| رخصة مؤقتة/تجريبية منتهية | التسجيل يبقى بعد الانتهاء | يتحول مع علامة التقييم المائية — watermarked: true |
كلا مساري الاستدعاء يحسبان العلامة وفقًا لنفس القاعدة: الواجهة DocumentConverter بلغة C# تستخرجها داخليًا من حالة IsViewerLicensed وIsTemporary في الرخصة، ومعالج ?convert=run في الأداة يجري الفحص المكافئ (IsViewerLicensed && !IsTrial && !IsTemporary) لملء الحقل watermarked الذي يُعيده. يمكن بناء واختبار تكامل من الطرف إلى الطرف على رخصة تقييم قبل الشراء — فقط بايتات المخرجات تتغير.
هل كانت هذه الصفحة مفيدة؟