תוסף ממיר
המרת מסמכים ל-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 ב‑overload של ה‑stream חייב לכלול את הנקודה המקדימה (".xlsx", ולא "xlsx") — הממיר משווה זאת מול קטלוג הפורמטים והרחבה ללא נקודה לא תיפתר. ולמרות שמו, WordToHtmlAsync מחזיר Task<Stream>, ולא Task<string> — אתה מקבל את מסמך ה‑HTML (תמונות משובצות כ‑Base64) כ‑stream, בדיוק כמו כל תוצאה אחרת של המרה.
פורמטים יעד
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 | כאשר מוגדר, ממיר את הודעת סימן המים על מסך התוצאה לקישור ל‑URL זה |
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(); // חזרה למסך idle/drop; לא מפעיל מחדש את onReady
conv.loadFile(file); // מתחיל את הזרימה עם אובייקט File; no-op אלא אם הוא כרגע במצב idle
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 — בתים של קובץ, 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 | verb 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 עצמו הוא חסר מצב ונפתר מהזרקת תלות; אל תבנה או תפסול את השירות באופן ידני.
לגבי הווידג'ט של האינטרנט, מאגרי ההעלאה וההורדה כוללים TTL של 30 דקות נפרדים. resultToken של הצופה פועל בהתאם למשך חיי סשן הצופה במקום זאת. סגירת תוצאת הצופה אינה מוחקת מאגר הורדה שעדיין תקף, והגדרת הווידג'ט בדפדפן מחדש אינה מאריכה אף אחד מה‑TTL.
פתרון בעיות
| סימפטום | בדיקה |
|---|---|
פתירת DocumentConverter נכשל | ההרשמה של ConverterPlugin התרחשה בתוך AddDoconut() |
| היישום נכשל בזמן ההפעלה | הרישיון שהוטען מעניק Converter |
| המרת הזרם אומרת שהפורמט אינו נתמך | sourceExtension כולל את הנקודה המקדימה |
| קוד ה‑JavaScript של הווידג'ט נטען אך הבקשות מחזירות 404 | AddConverterWidget() לא נקרא |
| בקשות הווידג'ט משתמשות ב‑URL שגוי | basePath תואם את הסניף שבו UseDoconut() ממופה |
| היעד חסר | השתמש בallowedTargets שמוחזר על ידי convert=open; לא כל מקור תומך בכל יעד של enum |
| ההורדה פגה | חזור על convert=open/convert=run; אסימוני המאגר הם זמניים בכוונה |
סימון מים
עם ConverterPlugin רשום, הרישיון של המארח נמצא באחד משלושה מצבים:
| מצב הרישיון | שער הפתיחה | פלט ההמרה |
|---|---|---|
רישיון צופה בתשלום המעניק Converter, בתוך תקופת התוקף שלו | עובר | נקי — watermarked: false |
| רישיון הערכה פעיל (דמו/NFR) | עובר | מומר בהצלחה, מסומן במים של ההערכה — watermarked: true |
ללא רישיון, קובץ TRIAL מיושן, או רישיון שאינו זמני שאינו מעניק Converter | היישום לעולם לא מתחיל — שער הפתיחה המתואר למעלה זורק | — |
| רישיון זמני/דמו שפג | ההרשמה נשארת לאחר הפקיעה | מומר עם סימן המים של ההערכה — watermarked: true |
שתי דרכי הקריאה מחשבות את הדגל מאותו כלל: הפסקה של DocumentConverter ב‑C# נגזרת פנימית ממצב ה‑IsViewerLicensed וה‑IsTemporary של הרישיון, והמתאם של ?convert=run בווידג'ט מבצע את הבדיקה המקבילה (IsViewerLicensed && !IsTrial && !IsTemporary) כדי למלא את השדה watermarked שהוא מחזיר. ניתן לבנות אינטגרציה ולבדוק אותה מקצה לקצה ברישיון הערכה לפני הרכישה — רק בתים הפלט משתנים.
האם דף זה היה מועיל?