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

Blazor Server:从网络共享加载图片到MemoryStream及API调用方案

解决方案

更简便的实现方式:直接在服务层访问网络共享

Blazor Server 运行在服务器端,代码执行权限等同于 IIS 应用池身份,因此可以跳过 API 层,直接在服务类中读取网络共享文件,无需通过 HttpClient 调用接口,这是最直接高效的方案。

步骤1:创建图片操作服务

定义服务接口和实现类,封装网络共享文件的读取逻辑:

public interface IPictureService
{
    Task<List<MemoryStream>> GetPicturesFromShareAsync(List<int> pictureIds);
    // 可扩展增删同步数据库等方法
}

public class PictureService : IPictureService
{
    private readonly string _sharePath = @"\\server\share\folder";
    private readonly YourDbContext _dbContext;

    public PictureService(YourDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<List<MemoryStream>> GetPicturesFromShareAsync(List<int> pictureIds)
    {
        var pictureStreams = new List<MemoryStream>();
        // 从数据库获取对应图片的文件名
        var pictures = await _dbContext.Pictures
            .Where(p => pictureIds.Contains(p.Id))
            .ToListAsync();

        foreach (var pic in pictures)
        {
            var filePath = Path.Combine(_sharePath, pic.FileName);
            if (!File.Exists(filePath)) continue;

            // 读取文件到MemoryStream
            using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            var memoryStream = new MemoryStream();
            await fileStream.CopyToAsync(memoryStream);
            memoryStream.Position = 0; // 重置流位置以便后续读取
            pictureStreams.Add(memoryStream);
        }

        return pictureStreams;
    }
}

步骤2:注册服务

在 Program.cs(.NET 5)中注册服务:

builder.Services.AddScoped<IPictureService, PictureService>();

步骤3:在Blazor页面中使用

注入服务后直接调用,同时处理资源释放:

@inject IPictureService PictureService
@implements IDisposable

<DxWizard ...>
    <!-- 向导内容:展示图片等操作 -->
</DxWizard>

@code {
    private List<MemoryStream> _pictureStreams;

    protected override async Task OnInitializedAsync()
    {
        // 假设从数据库获取需要加载的图片ID列表
        var pictureIds = await GetTargetPictureIdsAsync();
        _pictureStreams = await PictureService.GetPicturesFromShareAsync(pictureIds);
    }

    // 组件销毁时释放MemoryStream资源,避免内存泄漏
    public void Dispose()
    {
        if (_pictureStreams != null)
        {
            foreach (var stream in _pictureStreams)
            {
                stream.Dispose();
            }
            _pictureStreams.Clear();
        }
    }
}

关键注意事项

  • 权限配置:确保 IIS 应用池的运行身份(如域账户、本地系统账户)拥有网络共享文件夹的读取权限,否则会出现访问拒绝错误。
  • 资源释放:必须在组件销毁时手动释放 MemoryStream,避免内存泄漏。

若坚持使用API控制器+HttpClient方案:正确调用方式

如果需要通过API层解耦,可按以下步骤修复调用问题:

步骤1:确保API路由正确

检查 UploadController 中的 DownloadBDPicture 方法路由,示例:

[ApiController]
[Route("api/[controller]")]
public class UploadController : ControllerBase
{
    private readonly string _sharePath = @"\\server\share\folder";
    private readonly YourDbContext _dbContext;

    public UploadController(YourDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    [HttpGet("download/{pictureId}")]
    public async Task<IActionResult> DownloadBDPicture(int pictureId)
    {
        var picture = await _dbContext.Pictures.FindAsync(pictureId);
        if (picture == null) return NotFound();

        var filePath = Path.Combine(_sharePath, picture.FileName);
        if (!File.Exists(filePath)) return NotFound();

        var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        return File(stream, "image/jpeg", picture.FileName); // 根据实际图片类型调整MIME类型
    }
}

步骤2:在Blazor页面中正确调用API

注入 HttpClient 和 NavigationManager,构建绝对URI后调用:

@inject HttpClient Http
@inject NavigationManager NavManager
@implements IDisposable

<DxWizard ...>
    <!-- 向导内容 -->
</DxWizard>

@code {
    private List<MemoryStream> _pictureStreams;

    protected override async Task OnInitializedAsync()
    {
        var pictureIds = await GetTargetPictureIdsAsync();
        _pictureStreams = new List<MemoryStream>();

        foreach (var id in pictureIds)
        {
            // 构建API的绝对URL,解决相对路径调用失败问题
            var apiUrl = NavManager.ToAbsoluteUri($"/api/upload/download/{id}");
            // 获取响应流并转换为MemoryStream
            using var responseStream = await Http.GetStreamAsync(apiUrl);
            var memoryStream = new MemoryStream();
            await responseStream.CopyToAsync(memoryStream);
            memoryStream.Position = 0;
            _pictureStreams.Add(memoryStream);
        }
    }

    public void Dispose()
    {
        // 释放资源逻辑同前
        if (_pictureStreams != null)
        {
            foreach (var stream in _pictureStreams) stream.Dispose();
            _pictureStreams.Clear();
        }
    }
}

关键修复点

  • 绝对URI构建:使用 NavigationManager.ToAbsoluteUri 将相对API路径转换为绝对URL,解决HttpClient调用时的URI无效问题。
  • 流处理:确保将响应流复制到 MemoryStream 后重置位置,否则后续读取会从流末尾开始。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 01:17:40