תוסף ממיר
המרת מסמכים ל-45 פורמטים יעד
תוסף הממיר הופך את Doconut לשירות המרת מסמכים. הוא תורם את המנוע מאחורי הממשק הציבורי DocumentConverter, ו‑— באפשרותך לבחור — וידג'ט נשלף עם חוזה HTTP משלו, כך שאתה יכול להמיר מסמכים מ‑C#, מהווידג'ט, או מממשק משתמש שאתה בונה בעצמך.
התקנת החבילה
התקן את תוסף הממיר היציב האחרון:
dotnet add package Doconut.NETStandard.Converterכדי לעגן את התוסף לגרסה 26.8.0 הנוכחית, העבר את הגרסה בנפרד:
dotnet add package Doconut.NETStandard.Converter --version 26.8.0שמור על חבילת הממיר באותה גרסה כמו Doconut.NETStandard. מזהה החבילה הוא
Doconut.NETStandard.Converter; .26.8.0 מופיע רק בשם הקובץ שהורד .nupkg.
רישום התוסף
אין שיטה AddConverter() — מודל התוספים של Doconut אחיד. כל תוסף, כולל הממיר, נרשם באותו אופן: קרא AddPlugin<TPlugin>() בתוך AddDoconut(). ConverterPlugin מגיע בחבילת NuGet משלו, Doconut.NETStandard.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 בכל מקום שבו אתה צריך אותו — הוא חסר מצב לפי תכנון, ולכן ניתן להשתמש במופע יחיד בבטחה לאורך בקשות.
viewer.Converter.GetConverter() אינו קיים כאן. ההמרה כבר לא נגישה דרך מופע הצופה: הזרק Doconut.DocumentConverter במקום זאת.
// הזרק 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 על עומס ה‑stream חייב לכלול את הנקודה המקדימה (".xlsx", ולא "xlsx") — הממיר משווה זאת מול קטלוג הפורמטים והרחבה ללא נקודה לא תיפתר. ולמרות שמו, WordToHtmlAsync מחזיר Task<Stream>, ולא Task<string> — אתה מקבל את מסמך ה‑HTML (תמונות משובצות כ‑Base64) כ‑stream, בדיוק כמו כל תוצאה אחרת של המרה.
פורמטים יעד
ConversionTarget (מרחב שם Doconut.Configs.Conversion) מכיל 45 חברים:
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, Webp, Msg, Eml, Emlx, Mhtml,
Xlsm, Xlsb, Ppt, Docm, Dot, Dotx, Dotm, Vsdx, Vssx, Vstx, Vsdm, Vssm, Vstm,
Vdx, Vsx, Vtx, IcoEnum זה מכסה כל משפחת מקור. הספרייה הקודמת הייתה בעלת סוג *ConfigConverter לכל משפחה — WordConfigConverter, ExcelConfigConverter, וכן הלאה — כל אחד עם Enum מקונן EnTargetFormat משלו, בנוסף ל‑Enum SourceFormatConverter לקלט. כולם נעלמו; ראה את מדריך ההגירה.
לא כל מקור מומר לכל יעד — התוסף ממפה כל משפחת פורמט של מקור (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project/Task, PSD, מסמך אינטרנט) למערכת קבועה של יעדים מותרים. אל תקודד קבוע את ה‑Enum הזה כרשימת היעדים של הממשק שלך: ?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(); // חזרה למסך ההמתנה/הפלה; לא מפעיל מחדש את onReady
conv.loadFile(file); // מתחיל את הזרימה עם אובייקט File; no-op אלא אם הוא במצב idle
conv.destroy(); // מסיר מאזינים, מרוקן את ה‑mount; המופע אינו ניתן לשימוש לאחר מכןבניית ממשק משתמש משלך
הווידג'ט הוא רק לקוח עבור חוזה 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 ניתן לחיפוש הממוקם באפס. הקורא הוא הבעלים של הזרם הזה וצריך לשחררו לאחר ההעתקה או החזרת תוכנו. שירות 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 |
שתי דרכי הקריאה מחשבות את הדגל מאותו כלל: המעטפת C# של DocumentConverter מפיקה אותו פנימית ממצב IsViewerLicensed וIsTemporary של הרישיון, והמתאם ?convert=run של הווידג'ט מבצע את הבדיקה המקבילה (IsViewerLicensed && !IsTrial && !IsTemporary) כדי למלא את השדה watermarked שהוא מחזיר. ניתן לבנות אינטגרציה ולבדוק אותה מקצה לקצה על רישיון הערכה לפני רכישה — רק בתים הפלט משתנים.
האם דף זה היה מועיל?