Share via


Trabajo con imágenes en Blazor de ASP.NET Core

Nota

Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulte la versión .NET 8 de este artículo.

En este artículo se describen escenarios comunes para trabajar con imágenes en las aplicaciones de Blazor.

Establecer dinámicamente un origen de imagen

En el ejemplo siguiente se muestra cómo establecer dinámicamente el origen de una imagen con un campo de C#.

Para el ejemplo en esta sección:

  • Obtenga tres imágenes de cualquier origen o haga clic con el botón derecho en cada una de las imágenes siguientes para guardarlas localmente. Asigne a las imágenes los nombre image1.png, image2.png y image3.png.

    Icono de equipoIcono de carita felizIcono de la Tierra

  • Coloque las imágenes en una carpeta nueva llamada images en la raíz web de la aplicación (wwwroot). El uso de la carpeta images es solo con fines de demostración. Puede organizar las imágenes en la disposición de carpetas que prefiera, incluso servir las imágenes directamente desde la carpeta wwwroot.

En el componente ShowImage1 siguiente:

  • El origen de la imagen (src) se establece dinámicamente en el valor de imageSource en C#.
  • El método ShowImage actualiza el campo imageSource en función de un argumento id de imagen pasado al método.
  • Los botones representados llaman al método ShowImage con un argumento de imagen para cada una de las tres imágenes disponibles en la carpeta images. El nombre de archivo se compone mediante el argumento pasado al método y coincide con una de las tres imágenes de la carpeta images.

ShowImage1.razor:

@page "/show-image-1"

<PageTitle>Show Image 1</PageTitle>

<h1>Show Image Example 1</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id)
    {
        imageSource = $"images/image{id}.png";
    }
}
@page "/show-image-1"

<h1>Dynamic Image Source Example</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id)
    {
        imageSource = $"images/image{id}.png";
    }
}
@page "/show-image-1"

<h1>Dynamic Image Source Example</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id)
    {
        imageSource = $"images/image{id}.png";
    }
}

En el ejemplo anterior se usa un campo de C# para contener los datos de origen de la imagen, pero también se puede usar una propiedad de C# para contener los datos.

Nota

No use una variable de bucle directamente en una expresión lambda (como i en el ejemplo de bucle for anterior). de lo contrario, todas las expresiones lambda usarán la misma variable, con lo cual se usará el mismo valor en todas las expresiones lambda. Capture el valor de la variable en una variable local. En el ejemplo anterior:

  • La variable de bucle i se asigna a imageId.
  • imageId se usa en la expresión lambda.

Como alternativa, utilice un bucle foreach con Enumerable.Range, que no sufre el problema anterior:

@foreach (var imageId in Enumerable.Range(1,3))
{
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

Para más información, vea Control de eventos de Blazor en ASP.NET Core.

Transmisión de datos de imágenes

Se puede enviar una imagen directamente al cliente utilizando las características de interoperabilidad de streaming de Blazor en lugar de hospedar la imagen en una URL pública.

El ejemplo de esta sección transmite datos de origen de imágenes mediante la interoperabilidad de JavaScript (JS). La siguiente función setImage de JS acepta el id de etiqueta <img> y el flujo de datos para la imagen. La función realiza los pasos siguientes:

  • Lee la secuencia proporcionada en ArrayBuffer.
  • Crea un Blob para ajustar ArrayBuffer.
  • Crea una dirección URL de objeto para que sirva como dirección de la imagen que se va a mostrar.
  • Actualiza el elemento <img> con el imageElementId especificado con la dirección URL del objeto recién creada.
  • Para evitar pérdidas de memoria, la función llama a revokeObjectURL para eliminar la dirección URL del objeto cuando el componente termina de trabajar con una imagen.
<script>
  window.setImage = async (imageElementId, imageStream) => {
    const arrayBuffer = await imageStream.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const url = URL.createObjectURL(blob);
    const image = document.getElementById(imageElementId);
    image.onload = () => {
      URL.revokeObjectURL(url);
    }
    image.src = url;
  }
</script>

Nota:

Para obtener una guía general sobre la ubicación de JS y nuestras recomendaciones para aplicaciones de producción, consulte Ubicación de JavaScript en aplicaciones Blazor de ASP.NET Core.

El componente ShowImage2 siguiente:

  • Inserta servicios para System.Net.Http.HttpClient y Microsoft.JSInterop.IJSRuntime.
  • Incluye una etiqueta <img> para mostrar una imagen.
  • Tiene un método GetImageStreamAsync de C# para recuperar un Stream para una imagen. Una aplicación de producción puede generar dinámicamente una imagen basada en el usuario específico o recuperar una imagen del almacenamiento. En el ejemplo siguiente se recupera el avatar de .NET para el repositorio de GitHub dotnet.
  • Tiene un método SetImageAsync que se desencadena en la selección del botón por parte del usuario. SetImageAsync realiza las tareas siguientes:
    • Recupera el elemento Stream de GetImageStreamAsync.
    • Ajusta la clase Stream en un DotNetStreamReference, lo que permite el streaming de los datos de archivo al cliente.
    • Invoca la función setImage de JavaScript, que acepta los datos en el cliente.

Nota:

Las aplicaciones del lado servidor usan un servicio dedicado HttpClient para realizar solicitudes, por lo que el desarrollador de una aplicación del lado Blazor servidor no requiere ninguna acción para registrar un HttpClient servicio. Las aplicaciones HttpClient tienen un registro de servicio predeterminado Blazor cuando la aplicación se crea a partir de una plantilla de proyecto. Si un HttpClient registro de servicio no está presente en el Program archivo de una aplicación del lado cliente, proporcione uno agregando builder.Services.AddHttpClient();. Para más información, consulte Realización de solicitudes HTTP con IHttpClientFactory en ASP.NET Core.

ShowImage2.razor:

@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<PageTitle>Show Image 2</PageTitle>

<h1>Show Image Example 2</h1>

<p>
    <img id="image" />
</p>

<button @onclick="SetImageAsync">
    Set Image
</button>

@code {
    private async Task<Stream> GetImageStreamAsync()
    {
        return await Http.GetStreamAsync(
            "https://avatars.githubusercontent.com/u/9141961");
    }

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var dotnetImageStream = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setImage", "image", dotnetImageStream);
    }
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<h1>Stream Image Data Example</h1>

<p>
    <img id="image" />
</p>

<button @onclick="SetImageAsync">
    Set Image
</button>

@code {
    private async Task<Stream> GetImageStreamAsync()
    {
        return await Http.GetStreamAsync(
            "https://avatars.githubusercontent.com/u/9141961");
    }

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var dotnetImageStream = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setImage", "image", dotnetImageStream);
    }
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<h1>Stream Image Data Example</h1>

<p>
    <img id="image" />
</p>

<button @onclick="SetImageAsync">
    Set Image
</button>

@code {
    private async Task<Stream> GetImageStreamAsync()
    {
        return await Http.GetStreamAsync(
            "https://avatars.githubusercontent.com/u/9141961");
    }

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var dotnetImageStream = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setImage", "image", dotnetImageStream);
    }
}

Recursos adicionales