תוסף ממיר
המרת מסמכים ל-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 בכל מקום שבו אתה זקוק לו — הוא חסר‑מצב על‑פי‑תכנון, ולכן מופע יחיד בטוח לשימוש חוזר בין בקשות.
// Inject DocumentConverter; 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 בגרסת ה‑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, web document) למערך קבוע של יעדים מותרים. אל תקודד קבוע את המונה הזה ברשימת היעדים של הממשק שלך: ?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, הודעות שגיאה) |
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() מחזיר את מופע הוידג'ט עצמו — שמור עליו כדי לשלוט בוידג'ט תכנותית:
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> | המרת המקור השמור ל‑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, שדורשת נקודה.
מצבי כשל, מקובצים לפי נתיב
| נתיב | סטטוס | מתי | גוף |
|---|---|---|---|
| כל נתיב | 404 | הוידג'ט אינו מופעל (AddConverterWidget() לא נקרא) — נבדק לפני שכל אחד משלושת הנתיבים מתבצע | רק סטטוס |
| כל נתיב | 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 שניתן לחיפוש, ממוקם באפס. המבצע הוא בעל ה‑stream ויש לפנות אותו לאחר העתקה או החזרת תוכנו. שירות DocumentConverter עצמו חסר‑מצב ונפתר מה‑DI; אין לבנות או לשחרר את השירות באופן ידני.
לגבי וידג'ט האינטרנט, מאגרי ההעלאה וההורדה פועלים עם TTL של 30 דקות נפרד. אסימון resultToken של הצופה מתמשך לאורך חיי סשן הצופה. סגירת תוצאת הצופה אינה מוחקת מאגר הורדה שעדיין בתוקף, והפעלת הוידג'ט מחדש אינה מאריכה אף אחד מה‑TTL‑ים.
פתרון בעיות
| סימפטום | בדיקה |
|---|---|
קבלת DocumentConverter נכשלת | רישום ConverterPlugin בוצע בתוך AddDoconut() |
| האפליקציה נופלת בזמן האתחול | הרישיון שהוטען מעניק Converter |
| המרת ה‑Stream מדווחת שהפורמט אינו נתמך | sourceExtension כולל את הנקודה המקדימה |
| קובץ JavaScript של הוידג'ט נטען אך הבקשות מחזירות 404 | AddConverterWidget() לא נקרא |
| בקשות הוידג'ט משתמשות ב‑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 שהוא מחזיר. ניתן לבנות אינטגרציה ולבדוק קצה‑קצה על רישיון הערכה לפני רכישה — רק בתים של הפלט משתנים.
האם דף זה היה מועיל?