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

在Blazor页面中下载MemoryStream生成的TXT文件方案咨询

如何在Blazor中无临时文件下载MemoryStream中的ASCII艺术文件

这里提供两种无需创建服务器临时文件的解决方案,根据你的文件体积选择即可:


方案1:通过IJSRuntime调用JavaScript直接触发下载

无需额外接口,直接将ASCII文本内容传递给前端JS生成下载链接,适合大多数常规体积的文件。

步骤1:添加全局JavaScript函数

在项目的wwwroot/index.html(Blazor WebAssembly)或Pages/_Layout.cshtml(Blazor Server)中添加以下代码:

window.downloadFile = function (fileName, content, mimeType) {
    const blob = new Blob([content], { type: mimeType });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = fileName;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
};

步骤2:修改Blazor页面代码

调整文件上传后的处理逻辑,读取MemoryStream中的文本内容并调用JS函数:

@page "/"
@using ClassLibraryTransformImageToAsciiArt;
@using Microsoft.AspNetCore.Components.Forms
@using System.Text;

@inject IConvertImageToAsciiArt ConvertImageToAsciiArt
@inject IJSRuntime jsRuntime

<div class="container">
    <h1>Transform Images To Ascii Art</h1>
    <InputFile OnChange="@OnInputFileChange" />
</div>

@code {
    private long maxFileSize = 1024L * 1024L * 10L; //10 Mb

    private async Task OnInputFileChange(InputFileChangeEventArgs e)
    {
        using var imageStream = new MemoryStream();
        await e.File.OpenReadStream(maxAllowedSize: maxFileSize).CopyToAsync(imageStream);
        imageStream.Position = 0; // 重置流位置,确保转换方法能读取完整内容

        using var textFileStream = ConvertImageToAsciiArt.ConvertImageToAsciiArtStream(imageStream);
        textFileStream.Position = 0; // 重置流位置,准备读取ASCII内容

        // 将流内容读取为ASCII字符串
        var asciiContent = await new StreamReader(textFileStream, Encoding.ASCII).ReadToEndAsync();
        
        // 调用JS函数触发下载,自定义文件名
        await jsRuntime.InvokeVoidAsync("downloadFile", "ascii_art.txt", asciiContent, "text/plain");
    }
}

关键注意点

  • 必须重置Stream的Position为0,否则后续读取/转换会从流的末尾开始,导致内容为空
  • 使用using语句自动释放Stream资源,避免内存泄漏
  • 直接传递文本字符串比base64编码更高效,适合文本类文件

方案2:通过GET接口返回文件(适合超大文件场景)

如果ASCII内容体积极大,直接传递字符串到前端可能有性能问题,可以通过内存缓存暂存流,再通过API接口返回:

步骤1:注册内存缓存服务

在Program.cs中添加缓存服务:

builder.Services.AddMemoryCache();

步骤2:创建下载API控制器

新建AsciiDownloadController.cs:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;

[ApiController]
[Route("api/[controller]")]
public class AsciiDownloadController : ControllerBase
{
    private readonly IMemoryCache _cache;

    public AsciiDownloadController(IMemoryCache cache)
    {
        _cache = cache;
    }

    [HttpGet("{fileId}")]
    public IActionResult Download(string fileId)
    {
        if (_cache.TryGetValue<MemoryStream>(fileId, out var stream))
        {
            stream.Position = 0;
            // 下载完成后立即从缓存移除,释放内存
            _cache.Remove(fileId);
            return File(stream, "text/plain", "ascii_art.txt");
        }
        return NotFound();
    }
}

步骤3:修改Blazor页面代码

@page "/"
@using ClassLibraryTransformImageToAsciiArt;
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.Extensions.Caching.Memory
@using System.Guid;

@inject IConvertImageToAsciiArt ConvertImageToAsciiArt
@inject IJSRuntime jsRuntime
@inject IMemoryCache _cache

<div class="container">
    <h1>Transform Images To Ascii Art</h1>
    <InputFile OnChange="@OnInputFileChange" />
</div>

@code {
    private long maxFileSize = 1024L * 1024L * 10L; //10 Mb

    private async Task OnInputFileChange(InputFileChangeEventArgs e)
    {
        using var imageStream = new MemoryStream();
        await e.File.OpenReadStream(maxAllowedSize: maxFileSize).CopyToAsync(imageStream);
        imageStream.Position = 0;

        // 缓存存储的流不能用using,后续由控制器处理释放
        var textFileStream = ConvertImageToAsciiArt.ConvertImageToAsciiArtStream(imageStream);
        textFileStream.Position = 0;

        // 生成唯一ID标识缓存中的文件
        var fileId = Guid.NewGuid().ToString();
        // 设置5分钟过期时间,避免内存长期占用
        _cache.Set(fileId, textFileStream, TimeSpan.FromMinutes(5));

        // 调用JS打开下载链接
        await jsRuntime.InvokeVoidAsync("open", $"/api/AsciiDownload/{fileId}", "_blank");
    }
}

关键注意点

  • 必须设置缓存过期时间,防止内存泄漏
  • 接口返回文件后立即移除缓存条目,减少内存占用

内容的提问来源于stack exchange,提问作者Edgar Gomez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:05:33