blazor webassembly 中 c# 无法直接访问浏览器文件系统,因 wasm 运行在沙箱中且无操作系统文件句柄支持,所有文件操作必须通过 javascript 互操作调用浏览器原生 api 实现。

WebAssembly 中的 C# 无法直接访问浏览器文件系统
Blazor WebAssembly 运行在浏览器沙箱内,.NET 运行时被编译为 WebAssembly 字节码,System.IO 下的绝大多数类型(如 File、Directory、FileStream)在 WASM 环境中仅提供“存根实现”——调用会抛出 PlatformNotSupportedException。这不是权限问题,而是架构限制:WASM 没有操作系统级文件句柄概念,浏览器也禁止 JS/C# 直接读写本地磁盘路径。
必须通过 JavaScript 互操作桥接文件 API
所有真实文件操作(选择、读取、保存)都得委托给浏览器原生 API,再由 C# 通过 IJSRuntime 调用。关键路径是:<input type="file"> 触发选择 → JS 读取 File 对象 → 转为 ArrayBuffer 或 Uint8Array → 传回 C# 处理。
- 读取文件:用
JS.InvokeAsync<byte>("readFileAsBytes", fileInputElement)</byte>,JS 侧调用file.arrayBuffer()+new Uint8Array(buffer) - 保存文件:C# 生成
byte[]后,调用JS.InvokeVoidAsync("saveAsFile", fileName, bytes),JS 侧用Blob+URL.createObjectURL+<a download></a>触发下载 - 注意:大文件(>10MB)需分块或流式处理,避免 JS 堆内存溢出;
byte[]在跨语言传递时会完整复制,别直接传百 MB 数据
Microsoft.AspNetCore.Components.Forms.InputFile 是最简入口
这是 Blazor WASM 官方封装的文件输入组件,屏蔽了部分 JS 细节,但底层仍是调用浏览器 FileReader。它只支持单次选择后读取内容,不支持路径、元数据批量获取或后台监听。
- 使用时必须配合
@ref获取组件实例,再调用LoadFileAsync(返回IBrowserFile) -
IBrowserFile提供OpenReadStream()(返回Stream),但该流本质是内存流(已加载到 WASM 内存),不是文件句柄 - 不支持
SaveAs方法——它只负责“读入”,“写出”仍需你自己调 JS - 若需多文件、拖拽、预览,得额外写 JS 逻辑并注入事件回调,C# 侧用
JS.InvokeVoidAsync注册 handler
没有持久化存储,每次刷新即丢失
WASM 应用每次加载都是全新实例,MemoryStream、静态字段、甚至 localStorage(除非你主动写)里的二进制数据都不会自动保留。所谓“文件系统交互”,实际只是临时内存搬运。
- 想模拟“保存到本地”,只能触发浏览器下载(用户手动确认保存位置)
- 想缓存文件内容,需自己序列化后存入
localStorage(限小文本/JSON)或IndexedDB(需 JS 封装,C# 调用) - 不要尝试用
Path.GetTempPath()或类似 API——它们返回空字符串或抛异常
真正难的不是“怎么读一个文件”,而是设计好数据流转边界:哪些该存在浏览器端(IndexedDB)、哪些该立刻上传、哪些只需内存暂存。绕过 JS 直接操作文件,在当前 WASM 模型下根本不存在。










