Leer el HTML del editor de texto enriquecido en Blazor Server
Tarde o temprano, una página de Blazor Server tiene que llevar el HTML del editor a C# para guardarlo. La llamada obvia, JS.InvokeAsync<string>, funciona en las pruebas y luego falla con el primer documento largo, porque el resultado viaja por la conexión SignalR del circuito, que tiene un límite de mensaje de 32 KB. Esta página muestra qué ocurrió cuando lo alcanzamos y cómo el ejemplo lee el HTML como un flujo.
El límite de 32 KB
En Blazor Server, cada mensaje del navegador al servidor pasa por el circuito, y eso incluye el resultado de una llamada de JS interop. El MaximumReceiveMessageSize de SignalR para el circuito es de 32 KB de forma predeterminada. Devolvimos editor.getHTMLCode() a través de InvokeAsync<string> y medimos:
- 20,000 caracteres de HTML: llegaron.
- 40,000 caracteres: el navegador registró "Connection disconnected with error 'Error: Server returned an error on close: Connection closed with an error.'". El mensaje de la página no cambió, y el circuito había desaparecido.
Con el nivel de log predeterminado, el fallo no deja rastro en el servidor, así que es fácil pasarlo por alto en las pruebas.
Devuelve bytes desde JavaScript
Cuando una función de JS devuelve un Uint8Array, Blazor puede entregarlo a .NET como un IJSStreamReference, que se envía en fragmentos, fuera del límite de mensaje. Las funciones de interop del ejemplo están en App.razor:
<script>
// Called from Home.razor. The editor options stay in JavaScript, where they can also hold
// functions (custom buttons, event handlers) that cannot be sent from .NET as JSON.
window.rteBlazor = {
create: function (host) {
host.rte = new RichTextEditor(host, {
toolbar: "full",
galleryEndpoint: "/rte/gallery",
maxUploadFileSize: 4000000 // same limit as the server, checked before the upload starts
});
},
// Returned as bytes: .NET reads them as a stream, so documents over Blazor's 32 KB
// SignalR message limit still arrive.
getHtml: function (host) {
return new TextEncoder().encode(host.rte.getHTMLCode());
},
destroy: function (host) {
if (!host || !host.rte) return;
// editor.destroy() exists only in newer editor builds
if (typeof host.rte.destroy === "function") host.rte.destroy();
host.rte = null;
host.innerHTML = "";
}
};
</script>getHtml codifica el HTML como UTF-8 con TextEncoder. El editor en sí lo crea create; Añadir una galería de imágenes a un editor de texto enriquecido en Blazor explica create y destroy.
Lee el flujo en C#
async Task Save()
{
var bytes = await JS.InvokeAsync<IJSStreamReference>("rteBlazor.getHtml", host);
await using var stream = await bytes.OpenReadStreamAsync(maxAllowedSize: 10_000_000);
using var reader = new StreamReader(stream);
var html = await reader.ReadToEndAsync();
message = $"Saved {html.Length} characters of HTML."; // save html to your database here
}InvokeAsync<IJSStreamReference>pide los bytes como un flujo en lugar de como un valor.OpenReadStreamAsync(maxAllowedSize: 10_000_000)establece lo máximo que leerá el servidor. Su valor predeterminado es 512,000 bytes, así que ajústalo a lo que admita la columna de tu base de datos.StreamReadervuelve a convertir los bytes UTF-8 en una cadena. Guárdala a partir de aquí, y sanéala antes de mostrarla a otros usuarios.
Con este código, un documento de 100,000 caracteres x más una imagen insertada llegó completo: "Saved 100116 characters of HTML."
Por qué no aumentar el límite
La otra salida es un MaximumReceiveMessageSize mayor en las opciones del hub, por ejemplo mediante AddInteractiveServerComponents().AddHubOptions(...). Eso aumenta el límite para todos los mensajes de todos los circuitos. No lo usamos ni lo probamos para esta página. El streaming mantiene el valor predeterminado y solo deja pasar el HTML, hasta el tamaño que elijas.
Las imágenes son otro caso: nunca pasan por el componente. Subir imágenes desde un editor de texto enriquecido en Blazor explica por qué el editor las envía a endpoints HTTP, de modo que el HTML guardado solo contiene sus URL.
Pruébalo
Ejecuta el proyecto de ejemplo de esta guía con dotnet run y abre http://localhost:5304. Pega un documento largo en el editor, o escribe unos párrafos y pégalos muchas veces, y haz clic en Save. El mensaje bajo el editor muestra el número de caracteres que llegaron a C#, muy por encima de 32 KB. Para ver el límite, cambia Save para que lea el HTML con InvokeAsync<string> desde una función de JS que devuelva getHTMLCode() como cadena, y vuelve a guardar el mismo documento: el circuito se cierra.