תוסף ממיר

המרת מסמכים ל-24 פורמטים יעד

תוסף הממיר הופך את Doconut לשירות המרת מסמכים. הוא תורם למנוע מאחורי המעטפת הציבורית DocumentConverter, וכן — באפשרות בחירה — וידג'ט מוכן לשימוש עם חוזה HTTP משלו, כך שניתן להמיר מסמכים מ‑C#, מהוידג'ט, או מממשק משתמש שאתה בונה בעצמך.

התקנת החבילה

התקן את תוסף הממיר היציב האחרון:

bash
dotnet add package Doconut.NET6.Converter

כדי לעגן את התוסף לגרסה הנוכחית 26.7.0, העבר את הגרסה בנפרד:

bash
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, המותקנת לצד חבילת הצופה הבסיסית.

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});

קריאה זו זורקת חריגה בזמן האתחול אם חסרה רישיון, קובץ TRIAL מיושן, או רישיון שאינו זמני שאינו מעניק את היכולת ConverterInvalidOperationException שמיוצרת מבפנים של AddDoconut(), לפני שהאפליקציה מתחילה לשרת בקשות. רישומי Demo/NFR זמניים מתקבלים; לאחר פקיעת תוקפם, ההמרה נשארת זמינה עם פלט מסומן במים. אין רמת חינם שקטה. ראה הגדרת רישיון כדי להבין איך רישיונות נטענים.

המרה מ‑C#

כל המרה מחזירה MemoryStream שניתן לחיפוש, ממוקמת ב‑0, מוכנה לקריאה או העתקה מיידית. קבל את DocumentConverter מה‑DI בכל מקום שבו אתה זקוק לו — הוא חסר‑מצב על‑פי‑תכנון, ולכן מופע יחיד בטוח לשימוש חוזר בין בקשות.

csharp
// Inject DocumentConverter; its constructor is internal, so never `new` it.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);
csharp
// 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);
csharp
Stream html = await converter.WordToHtmlAsync("report.docx", ct);
csharp
Stream docx = await converter.HtmlToWordAsync(html, ConversionTarget.Docx, ct);

שתי נקודות שיכולות לטעות בקלות: sourceExtension בגרסת ה‑stream חייב לכלול את הנקודה המקדימה (".xlsx", ולא "xlsx" ) — הממיר משווה זאת אל קטלוג הפורמטים ונקודה ללא קידומת לא תיפתר. ולמרות שמו, WordToHtmlAsync מחזיר Task<Stream>, ולא Task<string> — אתה מקבל את מסמך ה‑HTML (תמונות משובצות כ‑Base64) כ‑stream, בדיוק כמו כל תוצאה של המרה אחרת.

פורמטים יעד

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, web document) למערך קבוע של יעדים מותרים. אל תקודד קבוע את המונה הזה ברשימת היעדים של הממשק שלך: ?convert=open מחזיר את allowedTargets האמיתי עבור הקובץ שהועלה זה עתה, וזה מה שצריך להניע את בחירת היעד.

וידג'ט מוכן לשימוש

קצות הקצה ?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, הודעות שגיאה)

Callbacks:

Callbackמתבצע כאשרPayload
onReady()הוידג'ט רינדר את מסך ההמתנה/נחת
onSourceLoaded({ token, pages, sourceExt, allowedTargets })?convert=open מצליחאסימון סשן מקור, מספר עמודים, סיומת מקור (בלי נקודה), רשימת יעדים מותרים
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target })?convert=run מצליחאותם השדות כמו בתשובת הריצה, בנוסף ל‑target שנבחר
onDownload({ downloadName, downloadToken })המשתמש לוחץ על קישור ההורדהמתבצע יחד עם ההורדה הטבעית של הדפדפן — אינו תופס או מחליף אותה
onError({ phase, message })בקשת open או run נכשלתphase הוא 'open' או 'run'; message הוא הודעת השגיאה המסוננת מהשרת (או הודעת לקוח לבדיקת גודל העלאה)

Doconut.convert() מחזיר את מופע הוידג'ט עצמו — שמור עליו כדי לשלוט בוידג'ט תכנותית:

javascript
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset();         // חזרה למסך ההמתנה/נחת; לא מפעיל מחדש onReady
conv.loadFile(file);  // מתחיל את הזרימה עם אובייקט File; ללא‑פעולה אם אינו במצב המתנה
conv.destroy();       // מסיר מאזינים, מרוקן את המיקום; המופע אינו ניתן לשימוש לאחר מכן

בניית ממשק משתמש משלך

הוידג'ט הוא רק לקוח לחוזה HTTP הזה — בנה ממשק משתמש משלך נגדו ישירות לחוויית משתמש שונה. כל שלושת הנתיבים נמצאים תחת ענף ASP.NET שבו UseDoconut() מותקן (בדרך כלל /doconut):

נתיבמטרהתגובה מוצלחת
POST ?convert=open (multipart, שדה 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() לא נקרא) — נבדק לפני שכל אחד משלושת הנתיבים מתבצערק סטטוס
כל נתיב405verb 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 שניתן לחיפוש, ממוקם באפס. המבצע הוא בעל ה‑stream ויש לפנות אותו לאחר העתקה או החזרת תוכנו. שירות DocumentConverter עצמו חסר‑מצב ונפתר מה‑DI; אין לבנות או לשחרר את השירות באופן ידני.

לגבי וידג'ט האינטרנט, מאגרי ההעלאה וההורדה פועלים עם TTL של 30 דקות נפרד. אסימון resultToken של הצופה מתמשך לאורך חיי סשן הצופה. סגירת תוצאת הצופה אינה מוחקת מאגר הורדה שעדיין בתוקף, והפעלת הוידג'ט מחדש אינה מאריכה אף אחד מה‑TTL‑ים.

פתרון בעיות

סימפטוםבדיקה
קבלת DocumentConverter נכשלתרישום ConverterPlugin בוצע בתוך AddDoconut()
האפליקציה נופלת בזמן האתחולהרישיון שהוטען מעניק Converter
המרת ה‑Stream מדווחת שהפורמט אינו נתמךsourceExtension כולל את הנקודה המקדימה
קובץ JavaScript של הוידג'ט נטען אך הבקשות מחזירות 404AddConverterWidget() לא נקרא
בקשות הוידג'ט משתמשות ב‑URL שגויbasePath תואם לענף שבו UseDoconut() ממופה
יעד חסרהשתמש ב‑allowedTargets שהוחזר על‑ידי convert=open; לא כל מקור תומך בכל יעד enum
הורדה פגהחזור על convert=open/convert=run; אסימוני המאגר נועדו להיות זמניים

סימון במים

עם ConverterPlugin רשום, רישיון המארח נמצא באחת משלוש המצבים:

מצב רישיוןשער אתחולפלט המרה
רישיון צופה בתשלום שמעניק Converter, בתוקףעוברנקי — watermarked: false
רישיון הערכה פעיל (demo/NFR)עוברממיר בהצלחה, עם סימון מים של ההערכה — watermarked: true
ללא רישיון, קובץ TRIAL מיושן, או רישיון בלתי‑זמני שלא מעניק Converterהאפליקציה לעולם לא מתחילה — השער שתואר למעלה זורק חריגה
רישיון זמני/Demo פג תוקףהרישום נשאר אחרי הפקיעהממיר עם סימון מים של ההערכה — watermarked: true

שתי דרכי הקריאה מחשבות את הדגל מאותו כלל: המעטפת C# של DocumentConverter מחשבת זאת פנימית מהמצב של IsViewerLicensed ו‑IsTemporary ברישיון, והמתאם של הוידג'ט ב‑?convert=run מבצע את אותה בדיקה (IsViewerLicensed && !IsTrial && !IsTemporary) כדי למלא את השדה watermarked שהוא מחזיר. ניתן לבנות אינטגרציה ולבדוק קצה‑קצה על רישיון הערכה לפני רכישה — רק בתים של הפלט משתנים.

האם דף זה היה מועיל?