Wtyczka konwertera

Konwertuj dokumenty do 24 formatów docelowych

Wtyczka Converter przekształca Doconut w usługę konwersji dokumentów. Dostarcza silnik stojący za publiczną fasadą DocumentConverter oraz — opcjonalnie — gotowy widget udostępniany przez DocImage.axd, dzięki czemu możesz konwertować dokumenty z C#, z widgetu lub z własnego interfejsu front‑endowego.

Zainstaluj pakiet

powershell
Install-Package Doconut.NETFramework.Converter

Utrzymuj pakiet Converter w tej samej wersji co Doconut.NETFramework.

Zarejestruj wtyczkę

Każda wtyczka rejestruje się w ten sam sposób: AddPlugin<TPlugin>() w DoconutHost.Initialize.

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

Jeśli żadne aktywne licencje nie przyznają możliwości Converter — brak licencji, starszy plik TRIAL lub licencja bez tej funkcji — DoconutHost.Initialize zgłasza wyjątek w Application_Start. W System.Web oznacza to, że każde żądanie zwraca pusty kod 500, a przyczyna jest widoczna jedynie w dzienniku zdarzeń Windows (źródło ASP.NET). Tymczasowe licencje Demo/NFR są akceptowane. Zobacz Konfiguracja licencji.

Konwertuj z C#

Każda konwersja zwraca przeszukiwalny MemoryStream ustawiony na pozycję 0. DocumentConverter jest bezstanowy: pobierz go z DoconutHost.Services tam, gdzie jest potrzebny i używaj wielokrotnie.

csharp
// Resolve DocumentConverter from DoconutHost.Services; its constructor is internal, so never `new` it.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);
csharp
// 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);
csharp
Stream html = await converter.WordToHtmlAsync("report.docx", ct);
csharp
Stream docx = await converter.HtmlToWordAsync(html, ConversionTarget.Docx, ct);

Dwa szczegóły, które łatwo pomylić: sourceExtension w przeciążeniu przyjmującym strumień musi zawierać początkową kropkę (".xlsx", a nie "xlsx"), w przeciwnym razie nie zostanie rozpoznany. I pomimo nazwy, WordToHtmlAsync zwraca Task<Stream>, a nie Task<string> — dokument HTML (obrazy osadzone jako Base64) przychodzi jako strumień, tak jak każdy inny wynik.

W kontrolerze MVC 5

Uczyń akcję asynchroniczną i użyj await przy konwersji:

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

W Web Forms: nigdy nie blokuj konwersji

Strona Web Forms działa w jednowątkowym kontekście żądania. ConvertAsync wznawia się w tym kontekście po zakończeniu, więc strona, która czeka na wynik synchronicznie — .Result, .Wait(), .GetAwaiter().GetResult() — blokuje wątek, którego konwersja potrzebuje do zakończenia. Żądanie nigdy nie powraca. Przeglądarka wciąż się kręci, IIS nie zapisuje żadnych logów, a reszta witryny działa, więc wygląda to jak wolna konwersja, a nie zakleszczenie.

Oznacz stronę Async="true" i uruchom konwersję jako asynchroniczne zadanie strony:

aspx
<%@ Page Language="C#" Async="true" CodeBehind="Convert.aspx.cs" Inherits="MyApp.Convert" %>
csharp
// Web Forms: the @Page directive needs Async="true", and the conversion runs as a page async task.
// Blocking on it instead (.Result, .Wait(), .GetAwaiter().GetResult()) deadlocks the request:
// it never returns, and nothing is logged.
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, not HttpContext.Current: after an await the latter can be null.
            Context.ApplicationInstance.CompleteRequest();
        }
    }));
}

Bez Async="true" w dyrektywie @Page, RegisterAsyncTask jest cicho pomijany. Po await użyj Context strony; HttpContext.Current może być w tym miejscu null.

Formaty docelowe

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

Nie każdy źródłowy format konwertuje na każdy docelowy: każda rodzina formatów źródłowych (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project, PSD, dokument internetowy) ma własny zestaw dozwolonych celów. Nie koduj na sztywno tego wyliczenia jako listy docelowej w interfejsie użytkownika: ?convert=open zwraca allowedTargets dla przesłanego pliku i to powinno sterować wyborem.

Wbudowany widżet

Endpointy widżetu ?convert=open|run|download są obsługiwane przez DocImage.axd i są wyłączone domyślnie. Włącz je obok rejestracji wtyczki:

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 reads the whole upload before Doconut sees it: keep maxRequestLength (KB) and
// maxAllowedContentLength (bytes) in Web.config above the widget's MaxUploadMb.
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>

Dwie rzeczy do sprawdzenia, gdy widżet zachowuje się nieprawidłowo:

  • basePath: '/DocImage.axd'. Domyślny basePath widżetu, /doconut, jest punktem końcowym ASP.NET Core. W tym pakiecie endpointy są obsługiwane przez handler DocImage.axd z Web.config.
  • Skrypt i endpointy są niezależne. Moduł zasobów serwuje doconutConverter.js niezależnie od tego, czy widżet jest włączony. Bez AddConverterWidget(), widżet ładuje się, rysuje swoją strefę upuszczania i wygląda całkowicie poprawnie — a jego pierwsza akcja zwraca 404.

Limity przesyłania

ASP.NET odczytuje całe ciało żądania przed uruchomieniem DocImage.axd. Przesył powyżej MaxUploadMb, ale poniżej limitów hosta, powoduje zwrócenie przez widżet własnego JSON 413 („Plik jest za duży.”). Przesył powyżej limitów hosta jest najpierw odrzucany przez IIS, z stroną błędu, której widżet nie może odczytać. Zachowaj oba limity hosta w Web.config powyżej limitu widżetu:

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>

Dostosowanie widżetu

Opcje przekazywane do Doconut.convert(selector, options):

OpcjaTypDomyślnieUwagi
basePathstring/doconutAdres URL punktu końcowego. Ustaw '/DocImage.axd' w tym pakiecie
resPathstring/doconut-resAkceptowane dla spójności z innymi widżetami Doconut; widżet konwertera nie buduje żadnego URL z tego
maxUploadMbnumber25Tylko wstępna weryfikacja po stronie klienta; serwer wymusza własny limit
licenseUrlstring | nullnullZamienia powiadomienie o znakowaniu wodnym na ekranie wyniku w link
labelsobject{}Zastępuje dowolny podzbiór angielskich ciągów widżetu

Wywołania zwrotne:

Wywołanie zwrotneWywoływane gdyDane
onReady()Widżet wyrenderował ekran upuszczania—
onSourceLoaded({ token, pages, sourceExt, allowedTargets })?convert=open zakończyło się sukcesemToken źródła, liczba stron, rozszerzenie źródła (bez kropki), dozwolone cele
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target })?convert=run zakończyło się sukcesemOdpowiedź po uruchomieniu plus żądany target
onDownload({ downloadName, downloadToken })Użytkownik kliknął PobierzWywoływane równocześnie z własnym pobieraniem przeglądarki
onError({ phase, message })Żądanie open lub run nie powiodło sięphase to 'open' lub 'run'; message to oczyszczony błąd serwera

Doconut.convert() zwraca instancję widżetu: reset() przywraca ekran upuszczania, loadFile(file) rozpoczyna proces z File, a destroy() usuwa go.

Zbuduj własny frontend

Widżet jest klientem tego kontraktu HTTP na DocImage.axd:

ŚcieżkaCelOdpowiedź sukcesu
POST /DocImage.axd?convert=open (multipart, pole file)Prześlij i otwórz dokument źródłowy200 — { token, pages, sourceExt, allowedTargets }
POST /DocImage.axd?token=<token>&convert=run&target=<ext>Konwertuj przesłany dokument źródłowy na target200 — { downloadToken, resultToken, resultPages, downloadName, watermarked }
GET /DocImage.axd?convert=download&token=<downloadToken>Strumieniuj skonwertowany plik200 — plik, Content-Disposition: attachment

Przesłane źródła są przechowywane przez 30 minut; po tym czasie run zwraca 404 i plik musi zostać ponownie otwarty. downloadToken otrzymuje własne 30‑minutowe okno po zakończeniu konwersji. resultToken jest zwykłym tokenem przeglądarki, który obowiązuje przez cały czas trwania sesji przeglądarki.

sourceExt w odpowiedzi open nie zawiera wiodącej kropki ("docx") — w przeciwieństwie do parametru sourceExtension w ConvertAsync.

ŚcieżkaStatusKiedyTreść
dowolna404Widżet nie jest włączony (AddConverterWidget() nigdy nie został wywołany)tylko status
dowolna405Nieprawidłowa metoda (open/run wymagają POST, download wymaga GET)tylko status
open413Przesyłanie przekracza MaxUploadMb (ale nie limity IIS){ "error": "File is too large." }
open400Brak ciała multipart, brak pliku lub typ, którego nie można skonwertować{ "error": "..." }
open403Typ pliku wymaga funkcji, której licencja nie przyznaje{ "error": "..." }
run400Nieprawidłowy token, nieznany target lub cel nieobecny w allowedTargets{ "error": "..." }
run404Przesyłanie wygasło lub nigdy nie zostało otwarte{ "error": "Upload expired — please re-open the file." }
open, run500Przetwarzanie nie powiodło się{ "error": "<sanitized message>" }
download400 / 404Nieprawidłowy, nieznany lub wygasły token pobraniatylko status

Własność zasobów

Wywołujący jest właścicielem MemoryStream zwracanego przez konwersję i powinien go zwolnić po skopiowaniu lub zwróceniu (MVC File(stream, …) zwalnia go za Ciebie). Nie twórz ani nie zwalniaj DocumentConverter samodzielnie — jego konstruktor jest wewnętrzny.

Dodawanie znaków wodnych

Stan licencjiUruchomienieWynik konwersji
Płatna licencja przeglądarki przyznająca ConverterUruchamia sięCzysty — watermarked: false
Aktywna licencja tymczasowa/demoUruchamia sięKonwertuje z znakiem wodnym oceny — watermarked: true
Brak licencji, starszy plik TRIAL lub licencja bez ConverterApplication_Start rzuca wyjątek; każde żądanie zwraca pusty 500—
Wygasła licencja tymczasowa/demoUruchamia sięKonwertuje z znakiem wodnym oceny — watermarked: true

Integrację można zbudować i przetestować od początku do końca na licencji ewaluacyjnej przed zakupem — zmieniają się tylko bajty wyjściowe.

Rozwiązywanie problemów

ObjawSprawdź
Każde żądanie zwraca pusty 500 po dodaniu wtyczkiLicencja przyznaje Converter — dziennik zdarzeń Windows, źródło ASP.NET
Rozwiązywanie DocumentConverter rzuca wyjątekAddPlugin<ConverterPlugin>() znajduje się w DoconutHost.Initialize
Konwersja Web Forms nigdy nie zwracaStrona blokuje się na ConvertAsync — użyj Async="true" i RegisterAsyncTask
Strumieniowa konwersja informuje, że format nie jest obsługiwanysourceExtension zawiera wiodącą kropkę
Widżet ładuje się, ale jego żądania zwracają 404AddConverterWidget() nie został wywołany lub basePath nie jest '/DocImage.axd'
Duży upload wyświetla stronę błędu IIS zamiast komunikatu widżetumaxRequestLength / maxAllowedContentLength są niższe niż MaxUploadMb
Brak docelowego formatuUżyj allowedTargets z convert=open
Pobranie wygasłoPowtórz convert=open / convert=run; tokeny są celowo tymczasowe

Czy ta strona była pomocna?