# Preview Selected or Uploaded Image

## Environment

<table>
    <tbody>
        <tr>
            <td>Product</td>
            <td>FileSelect for Blazor, <br /> Upload for Blazor</td>
        </tr>
    </tbody>
</table>

## Description

This KB article answers the following questions:

* How to immediately display the uploaded image files in the Blazor app?
* How to render an image preview when using the Blazor FileSelect?
* How to show the uploaded file as a preview when using the Upload control? I prefer to show a Base64 image without saving the file to the server.
* How to preview the selected image in the Upload `OnSelect` event?
* How to get the raw file content from the Upload component and add it to a memory stream?

## Solution

Users can preview images that are uploaded through the [Upload component](https://www.telerik.com/blazor-ui/documentation/components/upload/overview) or selected through the [FileSelect component](https://www.telerik.com/blazor-ui/documentation/components/fileselect/overview).

In Blazor, [previewing images is easier when using the FileSelect](https://www.telerik.com/blazor-ui/documentation/knowledge-base/upload-preview-image#using-the-fileselect), but based on your requirements you might [choose the Upload over the FileSelect](https://www.telerik.com/blazor-ui/documentation/components/upload/overview#upload-vs-fileselect) or vice versa.

### Using the Upload

1. Set the [`Accept`, `AllowedExtensions`, and `MaxFileSize`](https://www.telerik.com/blazor-ui/documentation/components/upload/overview#upload-parameters) parameters of the Upload.
2. [Ensure the Blazor app can handle large uploaded files](https://www.telerik.com/blazor-ui/documentation/components/upload/overview#large-file-uploads) with a size that matches or exceeds `MaxFileSize`.
3. [Implement a controller action method to receive the uploaded files](https://www.telerik.com/blazor-ui/documentation/components/upload/overview#implement-controller-methods). Also see the [example on the Upload Events page](https://www.telerik.com/blazor-ui/documentation/components/upload/events#example).
4. Read the uploaded image(s) in the controller and return an image URL or [Base64 data URI](https://en.wikipedia.org/wiki/Data_URI_scheme) for the `<img>` tag(s) to render. You can choose to provide the original image to the UI or a smaller version for greater efficiency.
5. Subscribe to the [Upload `OnSuccess` event](https://www.telerik.com/blazor-ui/documentation/components/upload/events#onsuccess) to detect completed file uploads and obtain the `<img>` tag's `src` value. You can also use `OnSuccess` to detect file removals in the Upload component and remove the respective `<img>` tags.

You cannot preview the image in the Upload `OnSelect` event, because this event handler has no access to the file contents.

The `UploadController` class below assumes that the project name and namespace is `TelerikBlazorApp`.

> caption Preview uploaded images when using the Upload component

```RAZOR.skip-repl
@inject NavigationManager NavigationManager

<h2>Upload</h2>

<TelerikUpload Accept="@string.Join(",", ImageFileExtensions)"
               AllowedExtensions="@ImageFileExtensions"
               MaxFileSize="@MaxImageSize"
               SaveUrl="@ToAbsoluteUrl("api/upload/saveimage")"
               RemoveUrl="@ToAbsoluteUrl("api/upload/removeimage")"
               OnSuccess="@OnUploadSuccess">
</TelerikUpload>

<div class="image-preview">
    @foreach (var image in UploadImages)
    {
        <img src="@image.ImageSource" class="k-border-2 k-border-solid k-border-primary" />
    }
</div>

<style>
    .image-preview {
        display: flex;
        gap: 2em;
        flex-wrap: wrap;
        align-items: center;
    }

        .image-preview img {
            max-width: 200px;
            max-height: 200px;
        }
</style>

@code {
    private List<string> ImageFileExtensions { get; set; } = new List<string>() { ".jpg", ".jpeg", ".png", ".gif" };

    private int? MaxImageSize { get; set; } = 8 * 1024 * 1024;

    private List<ImageModel> UploadImages { get; set; } = new();

    private void OnUploadSuccess(UploadSuccessEventArgs args)
    {
        var fileInfo = args.Files.First();
    
        if (args.Operation == UploadOperationType.Upload)
        {
            UploadImages.Add(new ImageModel()
            {
                ImageId = fileInfo.Id,
                ImageSource = args.Request.ResponseText
            });
        }
        else
        {
            UploadImages.RemoveAll(x => x.ImageId == fileInfo.Id);
        }
    }

    private string ToAbsoluteUrl(string url)
    {
        return $"{NavigationManager.BaseUri}{url}";
    }

    public class ImageModel
    {
        public string ImageId { get; set; } = string.Empty;
        public string ImageSource { get; set; } = string.Empty;
    }
}
```

```C# Controller
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace TelerikBlazorApp.Controllers
{
    [Route("api/[controller]/[action]")]
    public class UploadController : ControllerBase
    {
        public IWebHostEnvironment HostingEnvironment { get; set; }

        public UploadController(IWebHostEnvironment hostingEnvironment)
        {
            HostingEnvironment = hostingEnvironment;
        }

        [HttpPost]
        public async Task<string> SaveImage(IFormFile files)
        {
            string response = "";

            if (files != null)
            {
                try
                {
                    // OPTION 1. Return a Base64 string and display the image source as a data URI.
                    // Not efficient for large files.

                    //var imageBytes = new byte[files.Length];
                    //await files.OpenReadStream().ReadAsync(imageBytes);
                    //response = $"data:image/{Path.GetExtension(files.FileName)};base64,{Convert.ToBase64String(imageBytes.ToArray())}";

                    // ===============

                    // OPTION 2. Save the image as a file and return the image URL.
                    // May not be efficient for large files. You can save another smaller version of the file.

                    var imageSaveLocation = Path.Combine(HostingEnvironment.WebRootPath, files.FileName);

                    using var imageStream = new FileStream(imageSaveLocation, FileMode.Create);
                    await files.CopyToAsync(imageStream);

                    response = files.FileName;
                }
                catch (Exception e)
                {
                    Response.StatusCode = 500;
                    await Response.WriteAsync($"File processing failed: {e.Message}");
                }
            }

            return response;
        }

        [HttpPost]
        public async Task<IActionResult> RemoveImage([FromForm] string files)
        {
            if (files != null)
            {
                try
                {
                    var imageLocation = Path.Combine(HostingEnvironment.WebRootPath, files);

                    if (System.IO.File.Exists(imageLocation))
                    {
                        System.IO.File.Delete(imageLocation);
                    }
                }
                catch
                {
                    Response.StatusCode = 500;
                    await Response.WriteAsync("File deletion failed.");
                }
            }

            return new EmptyResult();
        }
    }
}
```

### Using the FileSelect

1. Set the [`Accept`, `AllowedExtensions`, and `MaxFileSize`](https://www.telerik.com/blazor-ui/documentation/components/fileselect/overview#fileselect-parameters) parameters of the FileSelect.
2. [Increase the SignalR message size](https://www.telerik.com/blazor-ui/documentation/knowledge-base/common-increase-signalr-max-message-size) to match or exceed `MaxFileSize`.
3. Subscribe to the [FileSelect `OnSelect` event](https://www.telerik.com/blazor-ui/documentation/components/fileselect/events#onselect).
4. Read the selected image(s) and create a [Base64 data URI](https://en.wikipedia.org/wiki/Data_URI_scheme) for the `<img>` tag(s) to render.
5. (optional) Subscribe to the [FileSelect `OnRemove` event](https://www.telerik.com/blazor-ui/documentation/components/fileselect/events#onremove) to remove the image preview.

> caption Preview selected images when using the FileSelect component

```RAZOR
@using System.IO;

<h2>FileSelect</h2>

<TelerikFileSelect Accept="@string.Join(",", ImageFileExtensions)"
                   AllowedExtensions="@ImageFileExtensions"
                   MaxFileSize="@MaxImageSize"
                   OnSelect="@OnFileSelectSelect"
                   OnRemove="@OnFileSelectRemove">
</TelerikFileSelect>

@if (FileSelectImages.Any())
{
    <h2>Image Preview</h2>

    <div class="image-preview">
        @foreach (var image in FileSelectImages)
        {
            <img src="@image.ImageSource" class="k-border-2 k-border-solid k-border-primary" />
        }
    </div>
}

<style>
    .image-preview {
        display: flex;
        gap: 2em;
        flex-wrap: wrap;
        align-items: center;
    }

        .image-preview img {
            max-width: 200px;
            max-height: 200px;
        }
</style>

@code {
    private List<string> ImageFileExtensions { get; set; } = new List<string>() { ".jpg", ".jpeg", ".png", ".gif" };

    private int? MaxImageSize { get; set; } = 8 * 1024 * 1024;

    private List<ImageModel> FileSelectImages { get; set; } = new();

    private async Task OnFileSelectSelect(FileSelectEventArgs args)
    {
        foreach (var file in args.Files)
        {
            if (!file.InvalidExtension && !file.InvalidMaxFileSize)
            {
                var imageBytes = new byte[file.Size];
                await using MemoryStream ms = new MemoryStream(imageBytes);
                await file.Stream.CopyToAsync(ms);

                FileSelectImages.Add(new ImageModel()
                {
                    ImageId = file.Id,
                    ImageSource = $"data:image/{file.Extension};base64,{Convert.ToBase64String(ms.ToArray())}"
                });
            }
        }
    }

    private void OnFileSelectRemove(FileSelectEventArgs args)
    {
        foreach (var file in args.Files)
        {
            FileSelectImages.RemoveAll(x => x.ImageId == file.Id);
        }
    }

    public class ImageModel
    {
        public string ImageId { get; set; } = string.Empty;
        public string ImageSource { get; set; } = string.Empty;
    }
}
```

## See Also

* [Upload Overview](https://www.telerik.com/blazor-ui/documentation/components/upload/overview)
* [Handle Upload Events](https://www.telerik.com/blazor-ui/documentation/components/upload/events)
* [FileSelect Overview](https://www.telerik.com/blazor-ui/documentation/components/fileselect/overview)
* [Handle FileSelect Events](https://www.telerik.com/blazor-ui/documentation/components/fileselect/events)
