Blazor Working With Images Docs (#23720)

pull/23740/head
Tanay Parikh 2021-11-04 10:50:22 -07:00 committed by GitHub
parent c5d39d948d
commit 433d048484
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 211 additions and 4 deletions

View File

@ -50,12 +50,12 @@ For this demonstration, the app creates a 50 KB file of random data from a new b
}
```
Create a `DownloadFileFromStream` method that performs the following steps:
The following `DownloadFileFromStream` method performs the following steps:
* Retrieve the <xref:System.IO.Stream> from `GetFileStream`.
* Retrieves the <xref:System.IO.Stream> from `GetFileStream`.
* Specify a file name when file is saved on the user's machine. The following example names the file `log.bin`.
* Wrap the <xref:System.IO.Stream> in a <xref:Microsoft.JSInterop.DotNetStreamReference>, which allows streaming the file data to the client.
* Invoke `downloadFileFromStream`, which is a JavaScript function that accepts the data on the client. The `downloadFileFromStream` function is shown later in this article.
* Wraps the <xref:System.IO.Stream> in a <xref:Microsoft.JSInterop.DotNetStreamReference>, which allows streaming the file data to the client.
* Invokes `downloadFileFromStream`, which is a JavaScript function that accepts the data on the client. The `downloadFileFromStream` function is shown later in this article.
```razor
@code {

View File

@ -744,6 +744,7 @@ In Blazor Server, file data is streamed over the SignalR connection into .NET co
## Additional resources
* <xref:blazor/file-downloads>
* <xref:blazor/images>
* <xref:mvc/models/file-uploads#security-considerations>
* <xref:blazor/forms-validation>

View File

@ -0,0 +1,204 @@
---
title: Work with images in ASP.NET Core Blazor apps
author: TanayParikh
description: Learn how to work with images in ASP.NET Core Blazor apps.
monikerRange: '>= aspnetcore-6.0'
ms.author: taparik
ms.custom: mvc
no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR]
ms.date: 11/02/2021
uid: blazor/images
---
# Work with images in ASP.NET Core Blazor apps
This article describes common scenarios for working with images in Blazor apps.
## Dynamically set an image source
The following example demonstrates how to dynamically set an image's source with a C# field.
For the example in this section:
* Obtain three small PNG images from any source.
* Name the images `image1.png`, `image2.png`, and `image3.png`.
* Place the images in a new folder (`images`) in the app's static assets folder (`wwwroot`).
The following directory tree shows the images in the `wwwroot/images` folder:
* `wwwroot`
* ...
* `images`
* `image1.png`
* `image2.png`
* `image3.png`
In the following `ShowImage` component:
* The image's source (`src`) is dynamically set to the value of `imageSource` in C#.
* The `ShowImage` method updates the `imageSource` field based on an image `id` argument passed to the method.
* Rendered buttons call the `ShowImage` method with an image ID argument for each of the three available images in the `images` folder.
`Pages/ShowImage.razor`:
```razor
@page "/show-image"
@if (imageSource is not null)
{
<div>
<img src="@imageSource" />
</div>
}
@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";
}
}
```
The preceding example uses a C# field to hold the image's source data, but you can also use a C# property to hold the data.
> [!NOTE]
> Do **not** use a loop variable directly in a lambda expression, such as `i` in the preceding `for` loop example. Otherwise, the same variable is used by all lambda expressions, which results in use of the same value in all lambdas. Always capture the variable's value in a local variable and then use the local variable. In the preceding example:
>
> * The loop variable `i` is assigned to `imageId`.
> * `imageId` is used in the lambda expression.
## Streaming examples
The examples in this section stream image source data using JS interop. The following JavaScript `setImageUsingStreaming` function accepts the `<img>` tag `id` and data stream for the image. The function performs the following steps:
* Reads the provided stream into an [`ArrayBuffer`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer).
* Creates a [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob) to wrap the `ArrayBuffer`.
* Creates an object URL to serve as the address for the image to be shown.
* Updates the `<img>` element with the specified `imageElementId` with the object URL just created.
```javascript
async function setImageUsingStreaming(imageElementId, imageStream) {
const arrayBuffer = await imageStream.arrayBuffer();
const blob = new Blob([arrayBuffer]);
const url = URL.createObjectURL(blob);
document.getElementById(imageElementId).src = url;
}
```
To prevent memory leaks, call [`URL.revokeObjectURL()`](https://developer.mozilla.org/docs/Web/API/URL/revokeObjectURL) to dispose of the object URL (`url` in the preceding example) when the component is finished working with an image. In a form, the object URL is typically revoked after the user submits the form for processing, as the object URL is no longer required at that point.
```javascript
URL.revokeObjectURL(url);
```
### Stream image data to a client
Sometimes, it's necessary to send an image directly to the client instead of hosting the image in a public directory. The following guidance explains how how to accomplish this goal using Blazor's streaming interop features.
Add [`@inject`](xref:mvc/views/razor#inject) directives for the following services to a Razor component (`.razor`):
* <xref:System.Net.Http.HttpClient?displayProperty=fullName>
* <xref:Microsoft.JSInterop.IJSRuntime?displayProperty=fullName>
> [!NOTE]
> Blazor Server apps use a dedicated `HttpClient` service to make requests. If you haven't already added an `HttpClient` to the app's service collection, do so now by adding `builder.Services.AddHttpClient();` in the `Program.cs` file before `builder.Build()`. For more information, see <xref:fundamentals/http-requests>.
Add an `<img>` tag to display the image. Also, add a button to trigger .NET to send the image to the client with a click event handler that calls a `SetImageUsingStreamingAsync` method:
```razor
<img id="image1" />
<button @onclick="SetImageUsingStreamingAsync">
Set Image Using Image Stream
</button>
```
Add a C# method that retrieves a <xref:System.IO.Stream> for the image. At this point, you may dynamically generate an image based on the specific user or retrieve an image from storage. The following example retrieves the `dotnet` avatar from GitHub:
```razor
@code {
private async Task<Stream> GetImageStreamAsync()
{
return await HttpClient.GetStreamAsync(
"https://avatars.githubusercontent.com/u/9141961");
}
}
```
Add the following `SetImageUsingStreamingAsync` method, which is triggered on the button's selection by the user. `SetImageUsingStreamingAsync` performs the following steps:
* Retrieves the <xref:System.IO.Stream> from `GetImageStreamAsync`.
* Wraps the <xref:System.IO.Stream> in a <xref:Microsoft.JSInterop.DotNetStreamReference>, which allows streaming the image data to the client.
* Invokes `setImageUsingStreaming` ([shown earlier](#streaming-examples)), which is a JavaScript function that accepts the data on the client. The `setImageUsingStreaming` function is shown later in this article.
```razor
@code {
private async Task SetImageUsingStreamingAsync()
{
var imageStream = await GetImageStreamAsync();
var dotnetImageStream = new DotNetStreamReference(imageStream);
await JSRuntime.InvokeVoidAsync("setImageUsingStreaming",
"image1", dotnetImageStream);
}
}
```
### Preview an image provided by the `InputFile` component
Use the <xref:Microsoft.AspNetCore.Components.Forms.InputFile> component to read browser file data into .NET code. In some apps, you may wish to show a preview of a selected image.
Add an `<img>` tag for displaying the image preview in a Razor component (`.razor`):
```html
<img id="showImageHere" />
```
Add the following <xref:Microsoft.AspNetCore.Components.Forms.InputFile> tag to the component:
```razor
<InputFile OnChange="ResizeAndDisplayImageUsingStreaming" />
```
When a file is selected, the `ResizeAndDisplayImageUsingStreaming` method is called with <xref:Microsoft.AspNetCore.Components.Forms.InputFileChangeEventArgs>. Examine the following `ResizeAndDisplayImageUsingStreaming` method example:
```razor
@code {
private async Task ResizeAndDisplayImageUsingStreaming(InputFileChangeEventArgs e)
{
var imageFile = e.File;
var resizedImage =
await imageFile.RequestImageFileAsync("image/jpg", 250, 250);
var jsImageStream = resizedImage.OpenReadStream();
var dotnetImageStream = new DotNetStreamReference(jsImageStream);
await JSRuntime.InvokeVoidAsync("setImageUsingStreaming",
"showImageHere", dotnetImageStream);
}
}
```
The preceding `ResizeAndDisplayImageUsingStreaming` method performs the following steps:
* Accesses the <xref:Microsoft.AspNetCore.Components.Forms.InputFileChangeEventArgs.File> which is an <xref:Microsoft.AspNetCore.Components.Forms.IBrowserFile>.
* Requests an image file from the specified <xref:Microsoft.AspNetCore.Components.Forms.IBrowserFile> and resizes it to 250 pixels by 250 pixels.
* Opens a <xref:System.IO.Stream> to read the `resizedImage`.
* Wraps the `resizedImage` <xref:System.IO.Stream> in a <xref:Microsoft.JSInterop.DotNetStreamReference>, which allows streaming the image data to the client.
* Invokes `setImageUsingStreaming` ([shown earlier](#streaming-examples)), which is a JavaScript function that accepts the data on the client.
> [!NOTE]
> The image preview technique described in this section involves round-tripping the image data from the client to the server and back. In a future release, this aspect might be optimized to better facilitate image previews. In the meantime, you may elect to create an event listener for the `InputFile` component that captures the [`FileList`](https://developer.mozilla.org/docs/Web/API/FileList) and displays a preview using JavaScript.
## Additional resources
* <xref:blazor/file-uploads>
* <xref:blazor/file-downloads>
* <xref:blazor/js-interop/call-dotnet-from-javascript#stream-from-javascript-to-dotnet>
* <xref:blazor/js-interop/call-javascript-from-dotnet#stream-from-dotnet-to-javascript>

View File

@ -399,6 +399,8 @@
uid: blazor/js-interop/call-dotnet-from-javascript
- name: Call a web API
uid: blazor/call-web-api
- name: Images
uid: blazor/images
- name: Security and Identity
items:
- name: Overview