You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Blazor WebAssembly在Android拍照时出现内存不足异常

Blazor WebAssembly安卓拍照内存优化及最佳实践

问题根源

三星Galaxy Tab S7 FE的内置相机输出的图片分辨率极高(通常远超普通设备),即使通过RequestImageFileAsync缩放后,Blazor WebAssembly在将图片转为Base64格式时会产生额外30%的内存开销,加上浏览器沙箱的内存限制,极易触发内存不足崩溃。其他设备相机输出体积更小或浏览器内存管理更优,因此无此问题。

内存优化方案

1. 进一步压缩图片分辨率与质量

降低目标分辨率并添加质量参数,大幅减少图片体积:

private async Task OnFileSelection(InputFileChangeEventArgs e)
{
    using var imgFile = e.File;
    var currentImageType = imgFile.ContentType;

    // 降低分辨率至800x800,质量设为70(0-100)
    using var resizedImageFile = await imgFile.RequestImageFileAsync(currentImageType, 800, 800, 70);
    using var stream = resizedImageFile.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024);
    using var ms = new MemoryStream();
    await stream.CopyToAsync(ms);
    
    var imageBytes = ms.ToArray();
    imgUrl = $"data:{currentImageType};base64,{Convert.ToBase64String(imageBytes)}";

    // 手动清理内存辅助GC回收
    Array.Clear(imageBytes, 0, imageBytes.Length);
    ms.SetLength(0);

    StateHasChanged();
}
  • 使用using包裹所有可释放资源,确保及时释放内存。
  • 通过maxAllowedSize限制流大小,避免意外加载超大文件。

2. 替换Base64为Object URL(推荐)

Base64会增加内存占用,改用浏览器原生URL.createObjectURL直接处理文件流,内存效率更高:
首先添加JS交互代码:

<script>
    window.createImageUrl = file => URL.createObjectURL(file);
    window.revokeImageUrl = url => URL.revokeObjectURL(url);
</script>

Blazor组件代码:

@inject IJSRuntime JS
@implements IDisposable

<div>
    <InputFile OnChange="@OnFileSelection" id="ImageInput" accept="image/*"></InputFile>
    <img src="@imgUrl" style="max-width: 500px; max-height: 500px;">
</div>

@code {
    private string? imgUrl;

    private async Task OnFileSelection(InputFileChangeEventArgs e)
    {
        // 先释放旧的Object URL避免内存泄漏
        if (!string.IsNullOrEmpty(imgUrl))
        {
            await JS.InvokeVoidAsync("revokeImageUrl", imgUrl);
            imgUrl = null;
        }

        // 直接创建Object URL,无需转Base64
        imgUrl = await JS.InvokeAsync<string>("createImageUrl", e.File);
        StateHasChanged();
    }

    public void Dispose()
    {
        // 组件销毁时清理URL
        if (!string.IsNullOrEmpty(imgUrl))
        {
            _ = JS.InvokeVoidAsync("revokeImageUrl", imgUrl);
        }
    }
}
  • 此方式无需将整个图片加载到内存,浏览器直接处理文件流,内存占用大幅降低。

3. 限制文件类型与大小

在InputFile添加accept属性过滤非图片文件,同时在代码中限制文件大小:

<InputFile OnChange="@OnFileSelection" id="ImageInput" accept="image/*"></InputFile>
private async Task OnFileSelection(InputFileChangeEventArgs e)
{
    var imgFile = e.File;
    if (imgFile.Size > 5 * 1024 * 1024) // 限制为5MB
    {
        await JS.InvokeVoidAsync("alert", "图片大小不能超过5MB,请选择更小的图片");
        return;
    }
    // 后续处理逻辑
}

最佳实践

  • 优先使用Object URL而非Base64,减少内存开销。
  • 始终用using包裹IBrowserFile、Stream等可释放资源,避免内存泄漏。
  • 针对三星等相机输出过大的设备,自动降低图片分辨率和质量。
  • 组件销毁时务必清理Object URL,防止浏览器内存泄漏。
  • 避免在Blazor中直接处理超大图片,尽量依托浏览器原生API处理。

内容的提问来源于stack exchange,提问作者Aiko West

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:25:31