תוסף ממיר
המרת מסמכים ל-24 פורמטים יעד
תוסף הממיר הופך את Doconut לשירות המרת מסמכים. הוא תורם את המנוע שמאחורי המ фасאדה הציבורית DocumentConverter, ו‑— באפשרות בחירה — וידג'ט נשלף עם חוזה HTTP משלו, כך שניתן להמיר מסמכים מ‑C#, מהווידג'ט, או מממשק חזיתי שאתה בונה בעצמך.
התקנת החבילה
התקן את תוסף הממיר היציב האחרון:
dotnet add package Doconut.NET8.Converterכדי להצמיד את התוסף לגרסה הנוכחית 26.7.0, העבר את הגרסה בנפרד:
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, המותקנת יחד עם חבילת הצופה הבסיסית.
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 בכל מקום שבו אתה צריך אותו — הוא חסר מצב לפי תכנון, ולכן מופע יחיד בטוח לשימוש חוזר בין בקשות.
// 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) למערך קבוע של יעדים מותרים. אל תקודד קבוע את המונה הזה ברשימת היעדים של UI שלך: ?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, הודעות שגיאה) |
קריאות חזרה:
| 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 עצמו חסר מצב ונקבל מה‑dependency injection; אל תבנה או תסגור את השירות באופן ידני.
לגבי וידג'ט האינטרנט, מאגרי העלאה והורדה כוללים TTL של 30 דקות נפרד. resultToken של הצופה עוקב אחרי חיי סשן הצופה. סגירת תוצאת הצופה אינה מוחקת מאגר הורדה שעדיין תקף, והפעלת וידג'ט הדפדפן מחדש אינה מאריכה אף אחד מה‑TTL‑ים.
פתרון בעיות
| סימפטום | בדיקה |
|---|---|
קבלת DocumentConverter נכשלת | רישום ConverterPlugin בוצע בתוך AddDoconut() |
| האפליקציה נופלת בזמן האתחול | הרישיון הטעון מעניק Converter |
| המרת ה‑stream אומרת שהפורמט אינו נתמך | sourceExtension כולל את הנקודה המקדימה |
| JavaScript של הווידג'ט נטען אך הבקשות מחזירות 404 | AddConverterWidget() לא נקרא |
| בקשות הווידג'ט משתמשות ב‑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 שהוא מחזיר. ניתן לבנות אינטגרציה ולבדוק קצה‑קצה על רישיון הערכה לפני רכישה — רק בתים של הפלט משתנים.
האם דף זה היה מועיל?