ملحق التحويل
تحويل المستندات إلى 24 صيغة مستهدفة
ملحق Converter يحول Doconut إلى خدمة تحويل مستندات. يضيف المحرك وراء الواجهة العامة DocumentConverter — وبالإضافة إلى ذلك — عنصر واجهة يمكن دمجه يُقدَّم عبر DocImage.axd، بحيث يمكنك تحويل المستندات من C#، أو من العنصر، أو من الواجهة الأمامية التي تبنيها بنفسك.
تثبيت الحزمة
Install-Package Doconut.NETFramework.Converterاحتفظ بحزمة Converter بنفس نسخة Doconut.NETFramework.
تسجيل الملحق
كل ملحق يُسجَّل بنفس الطريقة: AddPlugin<TPlugin>() داخل DoconutHost.Initialize.
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 (المصدر ASP.NET). تُقبل تراخيص Demo/NFR المؤقتة. راجع إعداد الترخيص.
التحويل من C#
كل عملية تحويل تُعيد MemoryStream قابل للبحث ومُحدَّد على الموضع 0. DocumentConverter لا يحتفظ بحالة: استدعِه من DoconutHost.Services أينما احتجت إليه وأعد استخدامه بحرية.
// 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);هناك تفصيلان سهلان الخطأ فيهما: يجب أن يتضمن sourceExtension في نسخة الدفق النقطة الأولية (".xlsx" وليس "xlsx")، وإلا لن يتم التعرف عليه. وعلى الرغم من اسمه، فإن WordToHtmlAsync يُعيد Task<Stream> وليس Task<string> — وثيقة HTML (الصور مدمجة كـ Base64) تصل كدفق، مثل كل نتيجة أخرى.
في وحدة تحكم MVC 5
اجعل الإجراء غير متزامن واستخدم await للتحويل:
[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 تُنفَّذ في سياق طلب أحادي الخيط. ConvertAsync تستأنف على ذلك السياق عند الانتهاء، لذا فإن الصفحة التي تنتظر النتيجة بشكل متزامن — .Result، .Wait()، .GetAwaiter().GetResult() — تحتجز الخيط الذي يحتاجه التحويل لإكمال عمله. الطلب لا يعود أبداً. المتصفح يظل يدور، ولا يُسجَّل شيء في IIS، وتستمر باقي أجزاء الموقع في العمل، فيظهر الأمر كتحويل بطيء وليس كـ deadlock.
ضع الخاصية Async="true" في الصفحة وشغِّل التحويل كمهمة غير متزامنة للصفحة:
<%@ 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();
}
}));
}بدون Async="true" في توجيه @Page، يتم تجاهل RegisterAsyncTask بصمت. بعد await، استخدم Context الخاص بالصفحة؛ قد يكون HttpContext.Current null هناك.
صيغ الهدف
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, مستند ويب) لها مجموعة خاصة من الأهداف المسموح بها. لا تقم بترميز هذه القائمة يدوياً كقائمة أهداف لواجهة المستخدم الخاصة بك: ?convert=open تُعيد allowedTargets للملف المرفوع، وهذا هو ما يجب أن يُستخدم لتحديد الاختيار.
عنصر واجهة المستخدم القابل للإدماج
نقاط النهاية ?convert=open|run|download للعنصر تُخدم بواسطة DocImage.axd وتكون معطلة بشكل افتراضي. قم بتمكينها بجوار تسجيل الإضافة:
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>شيئان يجب التحقق منهما عندما لا يعمل العنصر بشكل صحيح:
basePath: '/DocImage.axd'. الافتراضي للعنصر هو/doconutوهو نقطة النهاية لـ ASP.NET Core. في هذه الحزمة، نقاط النهاية هي المعالجDocImage.axdمنWeb.config.- السكريبت ونقاط النهاية مستقلان. وحدة الموارد تُقدم
doconutConverter.jsسواء كان العنصر مفعلاً أم لا. بدونAddConverterWidget(), يحمّل العنصر، يرسم منطقة السحب الخاصة به، ويظهر بشكل صحيح تماماً — وإجراءه الأول يُعيد404.
حدود التحميل
يقوم ASP.NET بقراءة كامل جسم الطلب قبل تشغيل DocImage.axd. إذا كان التحميل أعلى من MaxUploadMb ولكن أقل من حدود المضيف، يحصل العنصر على استجابة JSON 413 ("File is too large."). إذا كان التحميل أعلى من حدود المضيف، يتم رفضه من قبل IIS أولاً، مع صفحة خطأ لا يستطيع العنصر قراءتها. احتفظ بحدود المضيف في Web.config فوق حد العنصر:
<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):
| الخيار | النوع | الافتراضي | ملاحظات |
|---|---|---|---|
basePath | string | /doconut | عنوان URL لنقطة النهاية. اضبط '/DocImage.axd' في هذه الحزمة |
resPath | string | /doconut-res | مقبول للتوافق مع عناصر Doconut الأخرى؛ عنصر التحويل لا يُنشئ أي URL منه |
maxUploadMb | number | 25 | تحقق مسبق من جانب العميل فقط؛ الخادم يفرض الحد الخاص به |
licenseUrl | string | null | null | يحوّل إشعار العلامة المائية على شاشة النتيجة إلى رابط |
labels | object | {} | يتجاوز أي جزء من سلاسل العنصر الإنجليزية |
الاستدعاءات الراجعة:
| الاستدعاء | يُنفّذ عندما | الحمولة |
|---|---|---|
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() يُعيد نسخة العنصر: 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> | تحويل المصدر المرفوع إلى target | 200 — { 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 | الفعل غير صحيح (open/run يتطلبان POST، download يتطلب GET) | فقط الحالة |
open | 413 | الرفع يتجاوز MaxUploadMb (ولكن ليس حدود IIS) | { "error": "File is too large." } |
open | 400 | لا يوجد جسم multipart، لا ملف، أو نوع لا يمكن تحويله | { "error": "..." } |
open | 403 | نوع الملف يحتاج إلى قدرة لا تمنحها الرخصة | { "error": "..." } |
run | 400 | رمز غير صالح، target غير معروف، أو هدف غير موجود في allowedTargets | { "error": "..." } |
run | 404 | انتهت صلاحية الرفع أو لم يُفتح أبداً | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | فشل المعالجة | { "error": "<sanitized message>" } |
download | 400 / 404 | رمز تحميل غير صالح، غير معروف، أو منتهي الصلاحية | فقط الحالة |
ملكية الموارد
المستدعي يمتلك الـ MemoryStream الذي تُعيده عملية التحويل ويجب تحريره بعد النسخ أو الإرجاع (دالة File(stream, …) في MVC تقوم بتحريره لك). لا تقم بإنشاء أو تحرير DocumentConverter بنفسك — مُنشئه داخلي.
إضافة العلامة المائية
| حالة الترخيص | بدء التشغيل | نتيجة التحويل |
|---|---|---|
رخصة عارض مدفوعة تمنح Converter | يبدأ | نظيف — watermarked: false |
| رخصة مؤقتة/تجريبية نشطة | يبدأ | تحويل مع علامة مائية تجريبية — watermarked: true |
لا رخصة، ملف TRIAL قديم، أو رخصة بدون Converter | Application_Start يرمي استثناء؛ كل طلب يُجيب بـ 500 فارغ | — |
| رخصة مؤقتة/تجريبية منتهية | يبدأ | تحويل مع علامة مائية تجريبية — watermarked: true |
يمكن بناء واختبار التكامل من البداية إلى النهاية باستخدام رخصة تجريبية قبل الشراء — فقط بايتات الناتج تتغير.
استكشاف الأخطاء وإصلاحها
| العَرَض | التحقق |
|---|---|
كل طلب يُجيب بـ 500 فارغ بعد إضافة الإضافة | الرخصة تمنح Converter — سجل أحداث Windows، مصدر ASP.NET |
إيجاد DocumentConverter يرمي استثناء | AddPlugin<ConverterPlugin>() موجود في DoconutHost.Initialize |
| تحويل Web Forms لا يعود أبداً | الصفحة تتوقف على ConvertAsync — استخدم Async="true" و RegisterAsyncTask |
| تحويل الدفق يقول إن الصيغة غير مدعومة | sourceExtension يتضمن النقطة في البداية |
الودجت يُحمَّل لكن طلباته تُعيد 404 | AddConverterWidget() لم يُستدعَ، أو basePath ليس '/DocImage.axd' |
| رفع كبير يُظهر صفحة خطأ IIS بدلاً من رسالة الودجت | maxRequestLength / maxAllowedContentLength أقل من MaxUploadMb |
| هدف مفقود | استخدم allowedTargets من convert=open |
| انتهت صلاحية التحميل | أعد convert=open / convert=run؛ الرموز مؤقتة عن قصد |
هل كانت هذه الصفحة مفيدة؟