Plugin de conversion
Convertir des documents en 24 formats cibles
Le plugin Converter transforme Doconut en un service de conversion de documents. Il fournit le moteur derrière la façade publique DocumentConverter et — en option — un widget intégré servi par DocImage.axd, vous permettant de convertir des documents depuis C#, depuis le widget, ou depuis une interface que vous créez vous‑même.
Installer le paquet
Install-Package Doconut.NETFramework.ConverterConservez le paquet Converter à la même version que Doconut.NETFramework.
Enregistrer le plugin
Chaque plugin s’enregistre de la même manière : AddPlugin<TPlugin>() dans DoconutHost.Initialize.
Doconut.DoconutHost.Initialize(options =>
{
options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});Si aucune licence active n’accorde la capacité
Converter— aucune licence, un fichierTRIALhérité, ou une licence qui ne la possède pas —DoconutHost.Initializelève une exception depuisApplication_Start. Dans System.Web, cela signifie que chaque requête renvoie un500vide, et la raison n’apparaît que dans le journal d’événements Windows (source ASP.NET). Les licences temporaires Demo/NFR sont acceptées. Voir Configuration de licence.
Convertir depuis C#
Chaque conversion renvoie un MemoryStream recherchable positionné à 0. DocumentConverter est sans état : résolvez‑le depuis DoconutHost.Services où que vous en ayez besoin et réutilisez‑le librement.
// Resolve DocumentConverter from DoconutHost.Services; 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);Deux détails faciles à se tromper : sourceExtension dans la surcharge de flux doit inclure le point initial (".xlsx", pas "xlsx"), sinon la résolution échoue. Et malgré son nom, WordToHtmlAsync renvoie un Task<Stream>, pas un Task<string> — le document HTML (images intégrées en Base64) arrive sous forme de flux, comme tout autre résultat.
Dans un contrôleur MVC 5
Rendez l’action asynchrone et await la conversion :
[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");
}Dans Web Forms : ne jamais bloquer une conversion
Une page Web Forms s’exécute dans un contexte de requête mono‑thread. ConvertAsync reprend sur ce même contexte lorsqu’il se termine, de sorte qu’une page qui attend de façon synchrone — .Result, .Wait(), .GetAwaiter().GetResult() — monopolise le thread dont la conversion a besoin pour se terminer. La requête ne revient jamais. Le navigateur reste en attente, IIS n’enregistre rien, et le reste du site continue de fonctionner, ce qui donne l’impression d’une conversion lente plutôt que d’un blocage.
Marquez la page Async="true" et exécutez la conversion comme une tâche asynchrone de page :
<%@ Page Language="C#" Async="true" CodeBehind="Convert.aspx.cs" Inherits="MyApp.Convert" %>// 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();
}
}));
}Sans Async="true" dans la directive @Page, RegisterAsyncTask est silencieusement ignoré. Après un await, utilisez le Context de la page ; HttpContext.Current peut être null à cet endroit.
Formats cibles
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, WebpTous les formats source ne se convertissent pas en tous les formats cible : chaque famille de format source (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project, PSD, document web) possède son propre ensemble de cibles autorisées. Ne codez pas en dur cette énumération comme la liste des cibles de votre interface : ?convert=open renvoie les allowedTargets du fichier téléchargé, et c’est ce qui doit alimenter le sélecteur.
Widget intégrable
Les points de terminaison ?convert=open|run|download du widget sont fournis par DocImage.axd et sont désactivés par défaut. Activez‑les à côté de l’enregistrement du plugin :
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 lit l'intégralité du téléchargement avant que Doconut ne le voie : conservez maxRequestLength (KB) et
// maxAllowedContentLength (bytes) dans Web.config au-dessus du MaxUploadMb du widget.<div id="doconut-convert"></div>
<script src="/doconut-res/js/doconutConverter.js"></script>
<script>
Doconut.convert('#doconut-convert', { basePath: '/DocImage.axd', maxUploadMb: 25 });
</script>Deux points à vérifier lorsque le widget se comporte mal :
basePath: '/DocImage.axd'. Le défaut du widget,/doconut, est le point de terminaison ASP.NET Core. Dans ce package, les points de terminaison sont le gestionnaireDocImage.axdprovenant deWeb.config.- Le script et les points de terminaison sont indépendants. Le module de ressources sert
doconutConverter.jsque le widget soit activé ou non. SansAddConverterWidget(), le widget se charge, dessine sa zone de dépôt et apparaît parfaitement correct — et sa première action renvoie404.
Limites de téléchargement
ASP.NET lit l’intégralité du corps de la requête avant que DocImage.axd ne s’exécute. Un téléchargement supérieur à MaxUploadMb mais inférieur aux limites de l’hôte renvoie le JSON 413 du widget (« File is too large. »). Un téléchargement dépassant les limites de l’hôte est d’abord rejeté par IIS, avec une page d’erreur que le widget ne peut pas lire. Conservez les deux limites d’hôte dans Web.config au-dessus du plafond du widget :
<system.web>
<httpRuntime maxRequestLength="30720" /> <!-- KILOBYTES: 30 MB -->
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="31457280" /> <!-- BYTES: 30 MB -->
</requestFiltering>
</security>
</system.webServer>Personnaliser le widget
Options passées à Doconut.convert(selector, options) :
| Option | Type | Valeur par défaut | Remarques |
|---|---|---|---|
basePath | string | /doconut | L'URL du point de terminaison. Définissez '/DocImage.axd' pour ce package |
resPath | string | /doconut-res | Accepté pour la cohérence avec les autres widgets Doconut ; le widget de conversion ne construit aucune URL à partir de celui‑ci |
maxUploadMb | number | 25 | Vérification préliminaire côté client uniquement ; le serveur impose son propre plafond |
licenseUrl | string | null | null | Transforme l’avertissement de filigrane sur l’écran de résultat en lien |
labels | object | {} | Remplace tout sous‑ensemble des chaînes anglaises du widget |
Rappels :
| Rappel | Se déclenche quand | Charge utile |
|---|---|---|
onReady() | Le widget a affiché son écran de dépôt | — |
onSourceLoaded({ token, pages, sourceExt, allowedTargets }) | ?convert=open réussit | Jeton source, nombre de pages, extension source (sans point initial), cibles autorisées |
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target }) | ?convert=run réussit | La réponse d’exécution plus le target demandé |
onDownload({ downloadName, downloadToken }) | L'utilisateur clique sur Télécharger | Se déclenche en même temps que le téléchargement natif du navigateur |
onError({ phase, message }) | Une requête open ou run échoue | phase vaut 'open' ou 'run' ; message est l’erreur serveur sanitizée |
Doconut.convert() renvoie l’instance du widget : reset() revient à l’écran de dépôt, loadFile(file) lance le flux avec un File, et destroy() le supprime.
Créez votre propre interface frontale
Le widget est un client pour ce contrat HTTP sur DocImage.axd :
| Itinéraire | Objectif | Réponse réussie |
|---|---|---|
POST /DocImage.axd?convert=open (multipart, champ file) | Téléverser et ouvrir un document source | 200 — { token, pages, sourceExt, allowedTargets } |
POST /DocImage.axd?token=<token>&convert=run&target=<ext> | Convertir la source téléversée vers target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET /DocImage.axd?convert=download&token=<downloadToken> | Diffuser le fichier converti | 200 — le fichier, Content-Disposition: attachment |
Les sources téléversées sont conservées pendant 30 minutes ; passé ce délai, run renvoie 404 et le fichier doit être rouvert. downloadToken bénéficie de sa propre fenêtre de 30 minutes lorsque la conversion se termine. resultToken est un jeton de visualisation ordinaire qui suit la durée de vie de la session du visualiseur.
sourceExt dans la réponse open ne comporte pas de point initial ("docx") — le contraire du paramètre sourceExtension de ConvertAsync.
| Itinéraire | Statut | Quand | Corps |
|---|---|---|---|
| n'importe lequel | 404 | Le widget n'est pas activé (AddConverterWidget() n'a jamais été appelé) | statut uniquement |
| n'importe lequel | 405 | Verbe incorrect (open/run nécessitent POST, download nécessite GET) | statut uniquement |
open | 413 | Le téléversement dépasse MaxUploadMb (mais pas les limites IIS) | { "error": "File is too large." } |
open | 400 | Aucun corps multipart, aucun fichier, ou un type qui ne peut pas être converti | { "error": "..." } |
open | 403 | Le type de fichier nécessite une capacité que la licence n'accorde pas | { "error": "..." } |
run | 400 | Un jeton mal formé, un target inconnu, ou un target qui ne figure pas dans allowedTargets | { "error": "..." } |
run | 404 | Le téléversement a expiré ou n'a jamais été ouvert | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | Le traitement a échoué | { "error": "<sanitized message>" } |
download | 400 / 404 | Un jeton de téléchargement mal formé, inconnu ou expiré | statut uniquement |
Propriété des ressources
L'appelant possède le MemoryStream renvoyé par une conversion et doit le libérer après l'avoir copié ou renvoyé (la méthode File(stream, …) de MVC le libère pour vous). Ne construisez ni ne libérez vous‑même DocumentConverter — son constructeur est interne.
Filigrane
| État de la licence | Démarrage | Sortie de conversion |
|---|---|---|
Licence de visualisation payée accordant Converter | Démarre | Propre — watermarked: false |
| Licence temporaire/démo active | Démarre | Convertit, avec le filigrane d'évaluation — watermarked: true |
Aucune licence, un fichier TRIAL hérité, ou une licence sans Converter | Application_Start lève une exception ; chaque requête renvoie un 500 vide | — |
| Licence temporaire/démo expirée | Démarre | Convertit, avec le filigrane d'évaluation — watermarked: true |
Une intégration peut être construite et testée de bout en bout avec une licence d'évaluation avant l'achat — seuls les octets de sortie changent.
Dépannage
| Symptôme | Vérification |
|---|---|
Chaque requête renvoie un 500 vide après l'ajout du plugin | La licence accorde Converter — journal des événements Windows, source ASP.NET |
La résolution de DocumentConverter lève une exception | AddPlugin<ConverterPlugin>() se trouve dans DoconutHost.Initialize |
| Une conversion Web Forms ne renvoie jamais | La page bloque sur ConvertAsync — utilisez Async="true" et RegisterAsyncTask |
| La conversion de flux indique que le format n'est pas pris en charge | sourceExtension inclut le point initial |
Le widget se charge mais ses requêtes renvoient 404 | AddConverterWidget() n'a pas été appelé, ou basePath n'est pas '/DocImage.axd' |
| Un gros téléversement affiche une page d'erreur IIS au lieu du message du widget | maxRequestLength / maxAllowedContentLength sont inférieurs à MaxUploadMb |
| Un target est manquant | Utilisez allowedTargets provenant de convert=open |
| Le téléchargement a expiré | Refaites convert=open / convert=run ; les jetons sont temporaires de façon intentionnelle |
Cette page était-elle utile ?