Skip to content

API Proposal: Media components (Image, Video, FileDownload) #66391

@javiercn

Description

@javiercn

Background and Motivation

Blazor has no built-in way to display images, videos, or trigger file downloads from non-HTTP sources (byte arrays, streams, database BLOBs). Developers currently must base64-encode data (causing large string allocations) or create separate HTTP endpoints (which can interfere with authorization). Issue #25274 (20+ upvotes) has requested an Image component since 2020. This feature introduces a suite of media components using streaming JS interop and browser Cache Storage API for efficient data transfer.

PRs #63360 (Image) and #63540 (Media Suite — Video, FileDownload, MediaComponentBase, MediaSource, MediaContext). Related to issue #25274.

Proposed API

namespace Microsoft.AspNetCore.Components.Web.Media;

+ public class MediaSource
+ {
+     public MediaSource(byte[] data, string mimeType, string cacheKey);
+     public MediaSource(Stream stream, string mimeType, string cacheKey);
+     public string CacheKey { get; }
+     public long? Length { get; }
+     public string MimeType { get; }
+     public Stream Stream { get; }
+ }

+ public class MediaContext
+ {
+     public ElementReference Element { get; set; }
+     public bool HasError { get; }
+     public bool IsLoading { get; }
+     public string? ObjectUrl { get; }
+ }

+ public abstract class MediaComponentBase : ComponentBase, IAsyncDisposable
+ {
+     public Dictionary<string, object>? AdditionalAttributes { get; set; }
+     public MediaSource Source { get; set; }
+     public ValueTask DisposeAsync();
+ }

+ public class Image : MediaComponentBase
+ {
+     public RenderFragment<MediaContext>? ChildContent { get; set; }
+ }

+ public class Video : MediaComponentBase
+ {
+     public RenderFragment<MediaContext>? ChildContent { get; set; }
+ }

+ public class FileDownload : ComponentBase
+ {
+     public RenderFragment<FileDownloadContext>? ChildContent { get; set; }
+     public string FileName { get; set; }
+     public string? Text { get; set; }
+ }

+ public class FileDownloadContext
+ {
+     public string FileName { get; }
+     public Task InvokeAsync();
+ }

Usage Examples

Image from byte array:

@using Microsoft.AspNetCore.Components.Web.Media

<Image Source="new MediaSource(photoBytes, "image/jpeg", "photo-42")"
       alt="Product photo" />

Video from stream:

<Video Source="new MediaSource(videoStream, "video/mp4", "product-demo")"
       controls />

File download:

<FileDownload Source="new MediaSource(pdfData, "application/pdf", "report")"
              FileName="annual-report-2025.pdf"
              Text="Download Report" />

Alternative Designs

Base64 encoding (allocates large strings), creating separate HTTP endpoints (interferes with authorization, requires more work). The streaming approach avoids large .NET-side memory allocations and uses browser Cache Storage for repeat loads.

Risks

MediaSource is single-use (one instance per media load). The browser Cache Storage API is used for caching, which has storage limits depending on the browser.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-proposalapi-ready-for-reviewAPI is ready for formal API review - https://github.com/dotnet/apireviewsarea-blazorIncludes: Blazor, Razor Components

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions