Converter-Plugin

Dokumente in 24 Zielformate konvertieren

Das Converter-Plugin verwandelt Doconut in einen Dokumentkonvertierungsdienst. Es stellt die Engine hinter der öffentlichen DocumentConverter‑Fassade bereit und – optional – ein Drop‑in‑Widget, das von DocImage.axd bereitgestellt wird, sodass Sie Dokumente aus C#, aus dem Widget oder aus einem Frontend, das Sie selbst schreiben, konvertieren können.

Paket installieren

powershell
Install-Package Doconut.NETFramework.Converter

Halten Sie das Converter‑Paket in derselben Version wie Doconut.NETFramework.

Plugin registrieren

Jedes Plugin wird auf dieselbe Weise registriert: AddPlugin<TPlugin>() in DoconutHost.Initialize.

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

Wenn keine aktive Lizenz die Converter‑Fähigkeit gewährt — keine Lizenz, eine alte TRIAL‑Datei oder eine Lizenz ohne diese — wirft DoconutHost.Initialize beim Application_Start eine Ausnahme. In System.Web bedeutet das, dass jede Anforderung einen leeren 500 zurückgibt und die Ursache nur im Windows‑Ereignisprotokoll (Quelle ASP.NET) zu finden ist. Temporäre Demo‑/NFR‑Lizenzen werden akzeptiert. Siehe Lizenzsetup.

Konvertierung aus C#

Jede Konvertierung liefert einen seek‑fähigen MemoryStream, der bei 0 positioniert ist. DocumentConverter ist zustandslos: Lösen Sie ihn aus DoconutHost.Services auf, wo immer Sie ihn benötigen, und verwenden Sie ihn wiederholt.

csharp
// Löst DocumentConverter aus DoconutHost.Services auf; sein Konstruktor ist intern, daher niemals `new` verwenden.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);
csharp
// sourceExtension enthält den führenden Punkt. password ist null, sofern das Dokument nicht geschützt ist.
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);

Zwei Details, die leicht zu übersehen sind: sourceExtension bei der Stream‑Überladung muss den führenden Punkt enthalten (".xlsx", nicht "xlsx"), sonst wird sie nicht aufgelöst. Und trotz ihres Namens gibt WordToHtmlAsync ein Task<Stream> zurück, nicht ein Task<string> — das HTML‑Dokument (Bilder eingebettet als Base64) kommt als Stream, wie jedes andere Ergebnis.

In einem MVC‑5‑Controller

Machen Sie die Aktion asynchron und await‑en Sie die Konvertierung:

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");
}

In Web Forms: Nie bei einer Konvertierung blockieren

Eine Web‑Forms‑Seite läuft in einem single‑threaded Request‑Context. ConvertAsync setzt die Ausführung in diesem Kontext fort, wenn sie fertig ist, sodass eine Seite, die synchron darauf wartet — .Result, .Wait(), .GetAwaiter().GetResult() — den einzigen Thread blockiert, den die Konvertierung zum Abschluss benötigt. Die Anforderung kehrt nie zurück. Der Browser dreht sich weiter, IIS protokolliert nichts und der Rest der Site funktioniert weiter, sodass es wie eine langsame Konvertierung und nicht wie ein Deadlock aussieht.

Markieren Sie die Seite mit Async="true" und führen Sie die Konvertierung als asynchronen Seiten‑Task aus:

aspx
<%@ Page Language="C#" Async="true" CodeBehind="Convert.aspx.cs" Inherits="MyApp.Convert" %>
csharp
// Web Forms: Die @Page-Direktive benötigt Async="true" und die Konvertierung läuft als asynchroner Seiten-Task.
// Das Blockieren darauf (.Result, .Wait(), .GetAwaiter().GetResult()) führt zu einem Deadlock der Anforderung:
// sie kehrt nie zurück und es wird nichts protokolliert.
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, nicht HttpContext.Current: nach einem await kann Letzteres null sein.
            Context.ApplicationInstance.CompleteRequest();
        }
    }));
}

Ohne Async="true" in der @Page‑Direktive wird RegisterAsyncTask stillschweigend ignoriert. Nach einem await verwenden Sie das Context der Seite; HttpContext.Current kann dort null sein.

Zielformate

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

Nicht jede Quelle lässt sich in jedes Ziel konvertieren: jede Formatfamilie der Quelle (Word, Excel, PowerPoint, PDF, CAD, Bild, E‑Mail, Diagramm, Projekt, PSD, Webdokument) hat ihr eigenes Set zulässiger Ziele. Kodieren Sie diese Aufzählung nicht fest in die Ziel‑Liste Ihrer Benutzeroberfläche: ?convert=open liefert die allowedTargets für die hochgeladene Datei, und diese sollten die Auswahl steuern.

Drop‑in‑Widget

Die Endpunkte des Widgets ?convert=open|run|download werden von DocImage.axd bereitgestellt und sind standardmäßig deaktiviert. Aktivieren Sie sie neben der Plugin‑Registrierung:

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 liest den gesamten Upload, bevor Doconut ihn sieht: Behalten Sie maxRequestLength (KB) und
// maxAllowedContentLength (Bytes) in Web.config über dem MaxUploadMb des Widgets bei.
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>

Zwei Dinge, die Sie prüfen sollten, wenn das Widget nicht korrekt funktioniert:

  • basePath: '/DocImage.axd'. Der Standardwert des Widgets, /doconut, ist der ASP.NET‑Core‑Endpunkt. In diesem Paket sind die Endpunkte der DocImage.axd‑Handler aus Web.config.
  • Das Skript und die Endpunkte sind unabhängig. Das Ressourcenmodul liefert doconutConverter.js, unabhängig davon, ob das Widget aktiviert ist. Ohne AddConverterWidget() wird das Widget geladen, zeichnet seine Drop‑Zone und sieht völlig korrekt aus – und seine erste Aktion liefert 404.

Upload‑Grenzen

ASP.NET liest den gesamten Anforderungstext, bevor DocImage.axd ausgeführt wird. Ein Upload, der MaxUploadMb überschreitet, aber unter den Host‑Grenzen liegt, führt zu dem eigenen JSON‑Fehler 413 („Datei ist zu groß.“) des Widgets. Ein Upload, der die Host‑Grenzen überschreitet, wird zuerst von IIS abgelehnt, mit einer Fehlermeldungsseite, die das Widget nicht lesen kann. Halten Sie beide Host‑Grenzen in Web.config über dem Limit des Widgets fest:

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 anpassen

Optionen, die an Doconut.convert(selector, options) übergeben werden:

OptionTypStandardHinweise
basePathstring/doconutDie URL des Endpunkts. Setzen Sie '/DocImage.axd' in diesem Paket
resPathstring/doconut-resAkzeptiert zur Konsistenz mit anderen Doconut‑Widgets; das Converter‑Widget erzeugt daraus keine URL
maxUploadMbnumber25Nur clientseitige Vorprüfung; der Server erzwingt sein eigenes Limit
licenseUrlstring | nullnullWandelt den Wasserzeichen‑Hinweis auf dem Ergebnisbildschirm in einen Link um
labelsobject{}Überschreibt beliebige Teilmenge der englischen Zeichenketten des Widgets

Callbacks:

CallbackWird ausgelöst, wennDaten
onReady()Das Widget hat seinen Drop‑Screen gerendert—
onSourceLoaded({ token, pages, sourceExt, allowedTargets })?convert=open erfolgreichQuell‑Token, Seitenanzahl, Quell‑Erweiterung (ohne führenden Punkt), zulässige Ziele
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target })?convert=run erfolgreichDie Run‑Antwort plus das angeforderte target
onDownload({ downloadName, downloadToken })Der Benutzer klickt auf DownloadWird zusammen mit dem eigenen Download des Browsers ausgelöst
onError({ phase, message })Eine open‑ oder run‑Anfrage schlägt fehlphase ist 'open' oder 'run'; message ist der bereinigte Server‑Fehler

Doconut.convert() gibt die Widget‑Instanz zurück: reset() kehrt zum Drop‑Screen zurück, loadFile(file) startet den Ablauf mit einer File, und destroy() entfernt sie.

Erstelle dein eigenes Frontend

Das Widget ist ein Client für diesen HTTP-Vertrag auf DocImage.axd:

RouteZweckErfolgsantwort
POST /DocImage.axd?convert=open (multipart, field file)Hochladen und Öffnen eines Quelldokuments200 — { token, pages, sourceExt, allowedTargets }
POST /DocImage.axd?token=<token>&convert=run&target=<ext>Konvertiere die hochgeladene Quelle zu target200 — { downloadToken, resultToken, resultPages, downloadName, watermarked }
GET /DocImage.axd?convert=download&token=<downloadToken>Stelle die konvertierte Datei als Stream bereit200 — die Datei, Content-Disposition: attachment

Hochgeladene Quellen werden 30 Minuten lang aufbewahrt; danach gibt run 404 zurück und die Datei muss erneut geöffnet werden. downloadToken erhält ein eigenes 30‑Minuten‑Fenster, wenn die Konvertierung abgeschlossen ist. resultToken ist ein gewöhnliches Viewer‑Token, das der Lebensdauer der Viewer‑Sitzung folgt.

sourceExt in der open‑Antwort hat keinen führenden Punkt ("docx") — das Gegenteil des Parameters sourceExtension von ConvertAsync.

RouteStatusWannInhalt
beliebig404Das Widget ist nicht aktiviert (AddConverterWidget() wurde nie aufgerufen)nur Status
beliebig405Falsches Verb (open/run erfordern POST, download erfordert GET)nur Status
open413Der Upload überschreitet MaxUploadMb (aber nicht die IIS‑Grenzen){ "error": "File is too large." }
open400Kein Multipart‑Body, keine Datei oder ein Typ, der nicht konvertiert werden kann{ "error": "..." }
open403Der Dateityp erfordert eine Fähigkeit, die die Lizenz nicht gewährt{ "error": "..." }
run400Ein fehlerhaftes Token, ein unbekanntes target oder ein Ziel, das nicht in allowedTargets enthalten ist{ "error": "..." }
run404Der Upload ist abgelaufen oder wurde nie geöffnet{ "error": "Upload expired — please re-open the file." }
open, run500Verarbeitung fehlgeschlagen{ "error": "<sanitized message>" }
download400 / 404Ein fehlerhaftes, unbekanntes oder abgelaufenes Download‑Tokennur Status

Ressourcenbesitz

Der Aufrufer besitzt den MemoryStream, den eine Konvertierung zurückgibt, und sollte ihn nach dem Kopieren oder Zurückgeben freigeben (MVCs File(stream, …) gibt ihn für Sie frei). Erstellen oder entsorgen Sie DocumentConverter nicht selbst — sein Konstruktor ist intern.

Wasserzeichen

LizenzstatusStartKonvertierungsausgabe
Bezahlte Viewer‑Lizenz, die Converter gewährtStartetSauber — watermarked: false
Aktive temporäre/Demo‑LizenzStartetKonvertiert mit dem Evaluationswasserzeichen — watermarked: true
Keine Lizenz, eine veraltete TRIAL‑Datei oder eine Lizenz ohne ConverterApplication_Start wirft eine Ausnahme; jede Anfrage liefert ein leeres 500—
Abgelaufene temporäre/Demo‑LizenzStartetKonvertiert mit dem Evaluationswasserzeichen — watermarked: true

Eine Integration kann End‑zu‑Ende auf einer Evaluationslizenz vor dem Kauf aufgebaut und getestet werden — nur die Ausgabebytes ändern sich.

Fehlerbehebung

SymptomPrüfung
Jede Anfrage liefert nach dem Hinzufügen des Plugins ein leeres 500Die Lizenz gewährt Converter — Windows‑Ereignisprotokoll, Quell‑ASP.NET
Auflösen von DocumentConverter wirft eine AusnahmeAddPlugin<ConverterPlugin>() befindet sich in DoconutHost.Initialize
Eine Web‑Forms‑Konvertierung gibt nie zurückDie Seite blockiert bei ConvertAsync — verwenden Sie Async="true" und RegisterAsyncTask
Stream‑Konvertierung meldet, dass das Format nicht unterstützt wirdsourceExtension enthält den führenden Punkt
Das Widget lädt, aber seine Anfragen liefern 404AddConverterWidget() wurde nicht aufgerufen, oder basePath ist nicht '/DocImage.axd'
Ein großer Upload zeigt eine IIS‑Fehlerseite anstelle der Widget‑NachrichtmaxRequestLength / maxAllowedContentLength liegen unter MaxUploadMb
Ein Ziel fehltVerwenden Sie die allowedTargets aus convert=open
Der Download ist abgelaufenWiederholen Sie convert=open / convert=run; die Tokens sind bewusst temporär

War diese Seite hilfreich?