Πρόσθετο Μετατροπέα

Μετατρέψτε έγγραφα σε 24 μορφές προορισμού

Το πρόσθετο Converter μετατρέπει το Doconut σε υπηρεσία μετατροπής εγγράφων. Συνεισφέρει τη μηχανή πίσω από τη δημόσια DocumentConverter όψη και — με επιλογή — ένα ενσωματωμένο συστατικό που παρέχεται από DocImage.axd, ώστε να μπορείτε να μετατρέπετε έγγραφα από C#, από το συστατικό ή από μια πρόσοψη που γράφετε μόνοι σας.

Εγκατάσταση του πακέτου

powershell
Install-Package Doconut.NETFramework.Converter

Διατηρήστε το πακέτο Converter στην ίδια έκδοση με το Doconut.NETFramework.

Καταχώριση του πρόσθετου

Κάθε πρόσθετο καταχωρίζεται με τον ίδιο τρόπο: AddPlugin<TPlugin>() στο DoconutHost.Initialize.

csharp
Doconut.DoconutHost.Initialize(options =>
{
    options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});

Αν καμία ενεργή άδεια δεν παρέχει τη δυνατότητα Converter — καμία άδεια, ένα παλιό αρχείο TRIAL, ή μια άδεια χωρίς αυτή — το DoconutHost.Initialize ρίχνει εξαίρεση από το Application_Start. Στο System.Web αυτό σημαίνει ότι κάθε αίτηση απαντά με ένα κενό 500, και ο λόγος είναι μόνο στο αρχείο καταγραφής των Windows (πηγή ASP.NET). Δέχονται προσωρινές άδειες Demo/NFR. Δείτε το Ρύθμιση Άδειας.

Μετατροπή από C#

Κάθε μετατροπή επιστρέφει ένα αναζητήσιμο MemoryStream τοποθετημένο στο 0. Το DocumentConverter είναι χωρίς κατάσταση: επιλύστε το από το DoconutHost.Services όπου το χρειάζεστε και επαναχρησιμοποιήστε το ελεύθερα.

csharp
// Ανακτήστε το DocumentConverter από το DoconutHost.Services· ο κατασκευαστής του είναι εσωτερικός, οπότε ποτέ μην το `new` it.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);
csharp
// Το sourceExtension περιλαμβάνει την αρχική τελεία. Το password είναι null εκτός αν το έγγραφο είναι προστατευμένο.
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 στην υπερφόρτωση ροής πρέπει να περιλαμβάνει την αρχική τελεία (".xlsx", όχι "xlsx"), αλλιώς δεν επιλύεται. Και παρά το όνομά του, το WordToHtmlAsync επιστρέφει Task<Stream>, όχι Task<string> — το έγγραφο HTML (εικόνες ενσωματωμένες ως Base64) φτάνει ως ροή, όπως κάθε άλλο αποτέλεσμα.

Σε έναν ελεγκτή MVC 5

Κάντε τη δράση ασύγχρονη και await τη μετατροπή:

csharp
[HttpPost]
public async Task<ActionResult> ToPdf(HttpPostedFileBase file)
{
    var converter = Doconut.DoconutHost.Services.GetRequiredService<DocumentConverter>();
    Stream pdf = await converter.ConvertAsync(
        file.InputStream, Path.GetExtension(file.FileName), ConversionTarget.Pdf,
        password: null, ct: Response.ClientDisconnectedToken);
    return File(pdf, "application/pdf", Path.GetFileNameWithoutExtension(file.FileName) + ".pdf");
}

Στα Web Forms: ποτέ μην μπλοκάρετε μια μετατροπή

Μια σελίδα Web Forms εκτελείται σε ένα μονονηματικό πλαίσιο αίτησης. Το ConvertAsync συνεχίζει σε αυτό το πλαίσιο όταν ολοκληρωθεί, έτσι μια σελίδα που περιμένει συγχρονισμένα — .Result, .Wait(), .GetAwaiter().GetResult() — κρατά το ίδιο νήμα που χρειάζεται η μετατροπή για να ολοκληρωθεί. Το αίτημα δεν επιστρέφει ποτέ. Ο περιηγητής συνεχίζει να περιστρέφεται, τα αρχεία καταγραφής IIS δεν δείχνουν τίποτα, και το υπόλοιπο του ιστότοπου συνεχίζει να λειτουργεί, οπότε φαίνεται σαν αργή μετατροπή αντί για αδιέξοδο.

Σημειώστε τη σελίδα Async="true" και εκτελέστε τη μετατροπή ως ασύγχρονη εργασία της σελίδας:

aspx
<%@ Page Language="C#" Async="true" CodeBehind="Convert.aspx.cs" Inherits="MyApp.Convert" %>
csharp
// Web Forms: η οδηγία @Page χρειάζεται Async="true", και η μετατροπή εκτελείται ως ασύγχρονη εργασία σελίδας.
// Το μπλοκάρισμα σε αυτό (.Result, .Wait(), .GetAwaiter().GetResult()) προκαλεί αδιέξοδο του αιτήματος:
// Δεν επιστρέφει ποτέ και δεν καταγράφεται τίποτα.
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) return;

    RegisterAsyncTask(new PageAsyncTask(async ct =>
    {
        var converter = Doconut.DoconutHost.Services.GetRequiredService<DocumentConverter>();

        using (var pdf = await converter.ConvertAsync(
                   Server.MapPath("~/App_Data/contract.docx"), ConversionTarget.Pdf, ct: ct))
        using (var ms = new MemoryStream())
        {
            if (pdf.CanSeek) pdf.Position = 0;
            await pdf.CopyToAsync(ms);

            Response.ContentType = "application/pdf";
            Response.AddHeader("Content-Disposition", "attachment; filename=contract.pdf");
            Response.BinaryWrite(ms.ToArray());
            // Context, όχι HttpContext.Current: μετά από await το δεύτερο μπορεί να είναι null.
            Context.ApplicationInstance.CompleteRequest();
        }
    }));
}

Χωρίς το Async="true" στην οδηγία @Page, το RegisterAsyncTask αγνοείται σιωπηρά. Μετά ένα await, χρησιμοποιήστε το Context της σελίδας· το HttpContext.Current μπορεί να είναι null εκεί.

Μορφές προορισμού

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, PSD, web document) έχει το δικό της σύνολο επιτρεπτών προορισμών. Μην κωδικοποιείτε σκληρά αυτό το enum ως τη λίστα στόχων του UI σας: ?convert=open επιστρέφει το allowedTargets για το ανεβασμένο αρχείο, και αυτό είναι ό,τι πρέπει να καθοδηγεί έναν επιλογέα.

Widget ενσωμάτωσης

Τα ?convert=open|run|download endpoints του widget εξυπηρετούνται από DocImage.axd και είναι απενεργοποιημένα από προεπιλογή. Ενεργοποιήστε τα δίπλα στην εγγραφή του plugin:

csharp
Doconut.DoconutHost.Initialize(options =>
{
    options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
    options.AddConverterWidget(widget =>
    {
        widget.MaxUploadMb = 25;
    });
});
// Το System.Web διαβάζει ολόκληρη τη μεταφόρτωση πριν το Doconut τη δει: διατηρήστε το maxRequestLength (KB) και
// maxAllowedContentLength (bytes) στο Web.config πάνω από το MaxUploadMb του widget.
html
<div id="doconut-convert"></div>
<script src="/doconut-res/js/doconutConverter.js"></script>
<script>
  Doconut.convert('#doconut-convert', { basePath: '/DocImage.axd', maxUploadMb: 25 });
</script>

Δύο πράγματα που πρέπει να ελέγξετε όταν το widget συμπεριφέρεται ακατάλληλα:

  • basePath: '/DocImage.axd'. Η προεπιλογή του widget, /doconut, είναι το endpoint του ASP.NET Core. Σε αυτό το πακέτο, τα endpoints είναι ο χειριστής DocImage.axd από το Web.config.
  • Το script και τα endpoints είναι ανεξάρτητα. Το resource module εξυπηρετεί doconutConverter.js είτε το widget είναι ενεργοποιημένο είτε όχι. Χωρίς AddConverterWidget(), το widget φορτώνει, σχεδιάζει τη ζώνη απόθεσής του και φαίνεται εντελώς σωστό — και η πρώτη του ενέργεια απαντά 404.

Όρια μεταφόρτωσης

Το ASP.NET διαβάζει ολόκληρο το σώμα του αιτήματος πριν τρέξει το DocImage.axd. Μια μεταφόρτωση πάνω από MaxUploadMb αλλά κάτω από τα όρια του host λαμβάνει το δικό του JSON 413 του widget ("File is too large."). Μια μεταφόρτωση πάνω από τα όρια του host απορρίπτεται πρώτα από το IIS, με μια σελίδα σφάλματος που το widget δεν μπορεί να διαβάσει. Διατηρήστε και τα δύο όρια του host στο Web.config πάνω από το όριο του widget:

xml
<system.web>
  <httpRuntime maxRequestLength="30720" />           <!-- KILOBYTES: 30 MB -->
</system.web>
<system.webServer>
  <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength="31457280" />  <!-- BYTES: 30 MB -->
    </requestFiltering>
  </security>
</system.webServer>

Προσαρμογή του widget

Επιλογές που περνούν στο Doconut.convert(selector, options):

ΕπιλογήΤύποςΠροεπιλογήΣημειώσεις
basePathstring/doconutΤο URL του endpoint. Ορίστε '/DocImage.axd' σε αυτό το πακέτο
resPathstring/doconut-resΑποδεκτό για συνέπεια με άλλα Doconut widgets· το widget μετατροπής δεν δημιουργεί κανένα URL από αυτό
maxUploadMbnumber25Μόνο προ-έλεγχος στην πλευρά του πελάτη· ο διακομιστής επιβάλλει το δικό του όριο
licenseUrlstring | nullnullΜετατρέπει την ειδοποίηση υδατογράφησης στην οθόνη αποτελεσμάτων σε σύνδεσμο
labelsobject{}Αντικαθιστά οποιοδήποτε υποσύνολο των αγγλικών συμβολοσειρών του widget

Κλήσεις επιστροφής:

ΚλήσηΣυμβαίνει ότανΔεδομένα
onReady()Το widget έχει αποδώσει την οθόνη απόθεσης—
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() επιστρέφει την παρουσία του widget: reset() επιστρέφει στην οθόνη απόθεσης, loadFile(file) ξεκινά τη ροή με ένα File, και destroy() το αφαιρεί.

Δημιουργήστε το δικό σας frontend

Το widget είναι ένας πελάτης για αυτή τη σύμβαση HTTP στο DocImage.axd:

ΔιαδρομήΣκοπόςΑπάντηση επιτυχίας
POST /DocImage.axd?convert=open (πολλαπλής μορφής, πεδίο file)Ανέβασμα και άνοιγμα ενός πηγαίου εγγράφου200 — { token, pages, sourceExt, allowedTargets }
POST /DocImage.axd?token=<token>&convert=run&target=<ext>Μετατροπή του ανεβασμένου πηγαίου σε target200 — { downloadToken, resultToken, resultPages, downloadName, watermarked }
GET /DocImage.axd?convert=download&token=<downloadToken>Ροή του μετατρεπόμενου αρχείου200 — το αρχείο, Content-Disposition: attachment

Τα ανεβασμένα πηγαία διατηρούνται για 30 λεπτά· μετά από αυτό, run απαντά 404 και το αρχείο πρέπει να ανοίξει ξανά. downloadToken λαμβάνει το δικό του παράθυρο 30 λεπτών όταν ολοκληρωθεί η μετατροπή. resultToken είναι ένα συνηθισμένο viewer token που ακολουθεί τη διάρκεια της συνεδρίας προβολέα.

sourceExt στην απάντηση open δεν έχει αρχική τελεία ("docx") — το αντίστροφο της παραμέτρου sourceExtension του ConvertAsync.

ΔιαδρομήΚατάστασηΠότεΣώμα
οποιοδήποτε404Το widget δεν είναι ενεργοποιημένο (AddConverterWidget() δεν κλήθηκε ποτέ)μόνο κατάσταση
οποιοδήποτε405Λάθος ρήμα (open/run απαιτούν POST, download απαιτεί GET)μόνο κατάσταση
open413Το ανέβασμα υπερβαίνει το MaxUploadMb (αλλά όχι τα όρια του IIS){ "error": "File is too large." }
open400Δεν υπάρχει σώμα πολλαπλής μορφής, κανένα αρχείο, ή τύπος που δεν μπορεί να μετατραπεί{ "error": "..." }
open403Ο τύπος αρχείου απαιτεί δυνατότητα που η άδεια δεν παρέχει{ "error": "..." }
run400Ένα κακοδιατυπωμένο token, ένα άγνωστο target, ή ένας προορισμός που δεν υπάρχει στο allowedTargets{ "error": "..." }
run404Το ανέβασμα έληξε ή δεν ανοίχθηκε ποτέ{ "error": "Upload expired — please re-open the file." }
open, run500Η επεξεργασία απέτυχε{ "error": "<sanitized message>" }
download400 / 404Ένα κακοδιατυπωμένο, άγνωστο ή ληγμένο token λήψηςμόνο κατάσταση

Ιδιοκτησία πόρων

Ο καλούντας κατέχει το MemoryStream που επιστρέφει μια μετατροπή και πρέπει να το αποδεσμεύσει μετά την αντιγραφή ή την επιστροφή του (το File(stream, …) του MVC το αποδεσμεύει για εσάς). Μην δημιουργείτε ή αποδεσμεύετε το DocumentConverter μόνοι σας — ο κατασκευαστής του είναι εσωτερικός.

Υδατογράφημα

Κατάσταση άδειαςΈναρξηΑποτέλεσμα μετατροπής
Πληρωμένη άδεια προβολέα που παρέχει ConverterΞεκινάΚαθαρό — watermarked: false
Ενεργή προσωρινή/δωρητική άδειαΞεκινάΜετατρέπει, με το υδατογράφημα αξιολόγησης — watermarked: true
Χωρίς άδεια, ένα παλιό αρχείο TRIAL, ή άδεια χωρίς ConverterApplication_Start προκαλεί εξαίρεση· κάθε αίτηση απαντά ένα κενό 500—
Ληγμένη προσωρινή/δωρητική άδειαΞεκινάΜετατρέπει, με το υδατογράφημα αξιολόγησης — watermarked: true

Μια ενσωμάτωση μπορεί να δημιουργηθεί και να δοκιμαστεί από άκρη σε άκρη με μια άδεια αξιολόγησης πριν από την αγορά — μόνο τα bytes εξόδου αλλάζουν.

Επίλυση προβλημάτων

ΣύμπτωμαΈλεγχος
Κάθε αίτηση απαντά ένα κενό 500 μετά την προσθήκη του pluginΗ άδεια παρέχει Converter — αρχείο καταγραφής Windows, πηγή ASP.NET
Η επίλυση του DocumentConverter προκαλεί εξαίρεσηAddPlugin<ConverterPlugin>() βρίσκεται στο DoconutHost.Initialize
Μια μετατροπή Web Forms δεν επιστρέφει ποτέΗ σελίδα μπλοκάρει στο ConvertAsync — χρησιμοποιήστε Async="true" και RegisterAsyncTask
Η μετατροπή ροής λέει ότι η μορφή δεν υποστηρίζεταιsourceExtension περιλαμβάνει την αρχική τελεία
Το widget φορτώνει αλλά τα αιτήματά του επιστρέφουν 404AddConverterWidget() δεν κλήθηκε, ή basePath δεν είναι '/DocImage.axd'
Ένα μεγάλο ανέβασμα εμφανίζει μια σελίδα σφάλματος IIS αντί για το μήνυμα του widgetmaxRequestLength / maxAllowedContentLength είναι κάτω από MaxUploadMb
Λείπει ένας προορισμόςΧρησιμοποιήστε το allowedTargets από το convert=open
Η λήψη έληξεΕπαναλάβετε convert=open / convert=run· τα tokens είναι προσωρινά επίτηδες

Ήταν αυτή η σελίδα χρήσιμη;