תוסף ממיר

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

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

התקנת החבילה

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

bash
dotnet add package Doconut.NET8.Converter

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

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

שמור על חבילת הממיר באותה גרסה כמו Doconut.NET8. מזהה החבילה הוא Doconut.NET8.Converter; .26.7.0 מופיע רק בשם הקובץ .nupkg שהורד.

רישום התוסף

אין שיטה AddConverter() — מודל הפלאגינים של Doconut אחיד. כל תוסף, כולל הממיר, נרשם באותו אופן: קרא AddPlugin<TPlugin>() בתוך AddDoconut(). 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 ניתנת לחיפוש הממוקמת ב‑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) למערך קבוע של יעדים מותרים. אל תקודד קבוע את המונה הזה ברשימת היעדים של UI שלך: ?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, הודעות שגיאה)

קריאות חזרה:

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 עצמו חסר מצב ונקבל מה‑dependency injection; אל תבנה או תסגור את השירות באופן ידני.

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

פתרון בעיות

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

סימון במים (Watermarking)

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

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

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

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