Wtyczka Konwertera
Konwertuj dokumenty do 24 formatów docelowych
Wtyczka Konwertera przekształca Doconut w usługę konwersji dokumentów. Dostarcza silnik stojący za publiczną fasadą DocumentConverter oraz — opcjonalnie — gotowy widget z własnym kontraktem HTTP, dzięki czemu możesz konwertować dokumenty z C#, z widgetu lub z własnego frontendu.
Instalacja pakietu
Zainstaluj najnowszą stabilną wtyczkę Konwertera:
dotnet add package Doconut.NET6.ConverterAby przypiąć wtyczkę do bieżącej wersji 26.7.0, podaj wersję osobno:
dotnet add package Doconut.NET6.Converter --version 26.7.0Utrzymuj pakiet Konwertera w tej samej wersji co Doconut.NET6. Identyfikator pakietu to
Doconut.NET6.Converter; .26.7.0 pojawia się wyłącznie w nazwie pobranego pliku .nupkg.
Rejestracja wtyczki
Nie ma metody AddConverter() — model wtyczek Doconut jest jednolity. Każda wtyczka, w tym Konwerter, rejestruje się w ten sam sposób: wywołaj AddPlugin<TPlugin>() wewnątrz AddDoconut(). ConverterPlugin jest dostarczany w własnym pakiecie NuGet, Doconut.NET6.Converter, zainstalowanym obok podstawowego pakietu przeglądarki.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});To wywołanie rzuca wyjątek przy uruchamianiu, gdy brakuje licencji, istnieje starszy plik
TRIALlub licencja nie‑tymczasowa nie przyznaje możliwościConverter—InvalidOperationExceptionzgłaszany wewnątrzAddDoconut(), zanim aplikacja zacznie obsługiwać żądania. Tymczasowe rejestracje Demo/NFR są akceptowane; po ich wygaśnięciu konwersja pozostaje dostępna z wodnym znakiem w wyniku. Nie ma cichego darmowego poziomu. Zobacz Ustawienia licencji, aby dowiedzieć się, jak ładowane są licencje.
Konwersja z C#
Każda konwersja zwraca strumień MemoryStream z możliwością przewijania, ustawiony na pozycję 0, gotowy do odczytu lub kopiowania od razu. Rozwiąż DocumentConverter z DI w miejscu, gdzie jest potrzebny — jest on bezstanowy z założenia, więc pojedyncza instancja może być bezpiecznie używana wielokrotnie w różnych żądaniach.
// 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);Dwa szczegóły, które łatwo pomylić: sourceExtension w przeciążeniu strumieniowym musi zawierać wiodącą kropkę (".xlsx", a nie "xlsx" ) — konwerter dopasowuje ją do katalogu formatów i sama kropka nie zostanie rozpoznana. I pomimo nazwy, WordToHtmlAsync zwraca Task<Stream>, a nie Task<string> — otrzymujesz dokument HTML (obrazy osadzone jako Base64) jako strumień, tak jak każdy inny wynik konwersji.
Formaty docelowe
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, WebpNie każdy źródłowy format konwertuje się na każdy docelowy — wtyczka mapuje rodzinę formatu źródłowego (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project/Task, PSD, web document) na własny, stały zestaw dozwolonych celów. Nie koduj na stałe tego wyliczenia jako listy docelowej w UI: ?convert=open zwraca rzeczywiste allowedTargets dla właśnie przesłanego pliku i to powinno sterować wyborem.
Gotowy widget
Endpointy widgetu ?convert=open|run|download są opcjonalne i domyślnie wyłączone — zabezpieczone z góry. Włącz je po stronie serwera, razem z rejestracją wtyczki:
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>Bez AddConverterWidget() trzy endpointy ?convert= zwracają 404 — ale plik JS jest nadal serwowany (to zwykły wbudowany zasób statyczny; tylko endpointy, z którymi się komunikuje, są zabezpieczone). AddConverterWidget() nadal wymaga, aby wtyczka Konwertera była zarejestrowana oraz aby licencja przyznawała Converter — nie przyznaje ona samodzielnie praw do konwersji.
Dostosowanie widgetu
Opcje inicjalizacyjne przekazywane do Doconut.convert(selector, options):
| Opcja | Typ | Domyślnie | Uwagi |
|---|---|---|---|
basePath | string | /doconut | Ścieżka bazowa dla endpointów ?convert=; musi odpowiadać gałęzi ASP.NET, w której rzeczywiście zamontowano UseDoconut() (zwykle koordynowane przez MiddlewarePath) |
resPath | string | /doconut-res | Akceptowane dla spójności konfiguracji z innymi widgetami Doconut; widget konwertera obecnie nie buduje żadnego URL z tego |
maxUploadMb | number | 25 | Tylko wstępna kontrola po stronie klienta — odrzuca zbyt duży plik przed wysłaniem. Serwer wymusza własny limit niezależnie i zwraca 413, jeśli zostanie przekroczony |
licenseUrl | string | null | null | Gdy ustawione, zamienia powiadomienie o znaku wodnym na ekranie wyniku w link do tego URL |
labels | object | {} | Zastępuje dowolny podzbiór domyślnych angielskich ciągów widgetu (tekst upuszczenia, przyciski, ogłoszenia aria-live, komunikaty o błędach) |
Wywołania zwrotne:
| Wywołanie zwrotne | Wywoływane gdy | Ładunek |
|---|---|---|
onReady() | Widget wyświetlił ekran bezczynności/upuszczenia | — |
onSourceLoaded({ token, pages, sourceExt, allowedTargets }) | ?convert=open zakończyło się sukcesem | token sesji źródła, liczba stron, rozszerzenie źródła (bez kropki), lista dozwolonych celów |
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target }) | ?convert=run zakończyło się sukcesem | te same pola co w odpowiedzi run, plus żądany target |
onDownload({ downloadName, downloadToken }) | Użytkownik kliknie link Pobierz | wywoływane równocześnie z natywnym pobraniem przeglądarki — nie przechwytuje ani nie zastępuje go |
onError({ phase, message }) | Żądanie open lub run nie powiodło się | phase to 'open' lub 'run'; message to oczyszczony komunikat serwera (lub komunikat po stronie klienta dla wstępnej kontroli rozmiaru) |
Doconut.convert() zwraca samą instancję widgetu — zachowaj ją, aby sterować widgetem programowo:
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset(); // powrót do ekranu bezczynności; nie wywołuje ponownie onReady
conv.loadFile(file); // rozpoczyna przepływ z obiektem File; nie robi nic, jeśli nie jest w stanie bezczynności
conv.destroy(); // usuwa nasłuchiwacze, opróżnia montaż; instancja po tym jest nieużytecznaZbuduj własny frontend
Widget jest jedynie klientem tego kontraktu HTTP — zbuduj własny frontend bezpośrednio przeciwko niemu, aby uzyskać inny UX. Wszystkie trzy trasy znajdują się pod gałęzią ASP.NET, w której zamontowano UseDoconut() (zwykle /doconut):
| Ścieżka | Cel | Odpowiedź sukcesu |
|---|---|---|
POST ?convert=open (multipart, pole file) | Przesłanie i otwarcie dokumentu źródłowego do podglądu | 200 — { token, pages, sourceExt, allowedTargets } |
POST ?token=<token>&convert=run&target=<ext> | Konwersja przechowywanego źródła do target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET ?convert=download&token=<downloadToken> | Strumieniowanie skonwertowanego pliku | 200 — bajty pliku, Content-Disposition: attachment, Cache-Control: no-store |
Przesłane bajty źródła są przechowywane po stronie serwera z TTL = 30 min; po upływie tego okna run zwraca 404 i plik trzeba ponownie otworzyć. Wynik konwersji pozostaje w tym samym magazynie — downloadToken otrzymuje własne, świeże 30‑minutowe okno po zakończeniu konwersji — natomiast resultToken jest zwykłym tokenem sesji przeglądarki, którego żywotność podąża za pamięcią sesji przeglądarki, niezależnie od magazynu.
sourceExt w odpowiedzi open nie zawiera wiodącej kropki (np. "docx" ) — jest to odwrotna konwencja w stosunku do parametru sourceExtension w DocumentConverter.ConvertAsync, który wymaga kropki.
Tryby błędów, pogrupowane według trasy:
| Ścieżka | Status | Kiedy | Treść |
|---|---|---|---|
| any | 404 | Widget nie jest włączony (AddConverterWidget() nie został wywołany) — sprawdzane przed obsługą którejkolwiek z trzech tras | tylko status |
| any | 405 | Nieprawidłowy verb HTTP (open/run wymagają POST; download wymaga GET) | tylko status |
open | 413 | Przesłany plik przekracza MaxUploadMb | { "error": "Plik jest za duży." } |
open | 400 | Brak ciała multipart, brak pliku lub rozszerzenie źródła, którego nie można skonwertować | { "error": "..." } |
run | 400 | Nieprawidłowy token (nie jest GUID) lub target nie da się sparsować do ConversionTarget | { "error": "Invalid token." } / { "error": "Unknown target format." } |
run | 400 | target nie znajduje się w allowedTargets źródła | { "error": "That target format is not available for this file." } |
run | 404 | Przechowywane przesłanie wygasło (TTL = 30 min) lub token nigdy nie został otwarty | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | Wewnętrzna awaria przetwarzania | { "error": "<sanitized message>" } — oczyszczany w ten sam sposób co każdy inny błąd Doconut; nigdy nie ujawnia wewnętrznych nazw silnika |
download | 400 | Nieprawidłowy token (nie jest GUID) | tylko status |
download | 404 | Nieznany lub wygasły token pobrania | tylko status |
Własność zasobów
Konwerter zwraca strumień MemoryStream z możliwością przewijania, ustawiony na pozycję 0. Wywołujący jest właścicielem tego strumienia i powinien go zwolnić po skopiowaniu lub zwróceniu jego zawartości. Usługa DocumentConverter jest bezstanowa i rozwiązywana z wstrzykiwania zależności; nie twórz ani nie zwalniaj jej ręcznie.
Dla widgetu webowego magazyny przesyłania i pobierania mają niezależne TTL = 30 min. Token resultToken przeglądarki podąża za okresem sesji przeglądarki. Zamknięcie wyniku przeglądarki nie usuwa nadal ważnego magazynu pobrania, a zresetowanie widgetu w przeglądarce nie przedłuża żadnego z TTL‑ów.
Rozwiązywanie problemów
| Objaw | Sprawdź |
|---|---|
Rozwiązywanie DocumentConverter nie powodzi się | Rejestracja ConverterPlugin odbyła się wewnątrz AddDoconut() |
| Aplikacja nie uruchamia się | Załadowana licencja przyznaje Converter |
| Konwersja strumienia zgłasza nieobsługiwany format | sourceExtension zawiera wiodącą kropkę |
| JavaScript widgetu ładuje się, ale żądania zwracają 404 | AddConverterWidget() nie został wywołany |
| Żądania widgetu używają niewłaściwego URL | basePath odpowiada gałęzi, w której zamapowano UseDoconut() |
| Brakuje docelowego formatu | Użyj allowedTargets zwróconych przez convert=open; nie każdy źródłowy format obsługuje każdy enum docelowy |
| Pobranie wygasło | Powtórz convert=open/convert=run; tokeny magazynu są celowo tymczasowe |
Znaki wodne
Po zarejestrowaniu ConverterPlugin licencja hosta znajduje się w jednym z trzech stanów:
| Stan licencji | Brama startowa | Wyjście konwersji |
|---|---|---|
Płatna licencja przeglądarki przyznająca Converter, w okresie ważności | Przechodzi | Czyste — watermarked: false |
| Aktywna licencja ewaluacyjna (demo/NFR) | Przechodzi | Konwertuje pomyślnie, oznaczone znakiem wodnym ewaluacji — watermarked: true |
Brak licencji, starszy plik TRIAL lub licencja nie‑tymczasowa nie przyznająca Converter | Aplikacja nigdy się nie uruchamia — opisany wyżej mechanizm startowy rzuca wyjątek | — |
| Wygasła licencja tymczasowa/demo | Rejestracja przetrwa wygaśnięcie | Konwertuje z znakiem wodnym ewaluacji — watermarked: true |
Obie ścieżki wywołań obliczają flagę według tej samej reguły: fasada C# DocumentConverter wyprowadza ją wewnętrznie z pól licencji IsViewerLicensed i IsTemporary, a obsługa ?convert=run w widgetcie wykonuje równoważny warunek (IsViewerLicensed && !IsTrial && !IsTemporary), aby wypełnić pole watermarked w zwracanej odpowiedzi. Integrację można zbudować i przetestować end‑to‑end na licencji ewaluacyjnej przed zakupem — zmieniają się jedynie bajty wyjściowe.
Czy ta strona była pomocna?