
Tauri 应用在 macOS 上无法通过 触发 Blob 下载,因安全策略禁止跨源 download 属性;需改用 Tauri 官方文件系统插件(如 @tauri-apps/plugin-fs 和 @tauri-apps/plugin-dialog)实现可控、跨平台的本地文件保存。
tauri 应用在 macos 上无法通过 `` 触发 blob 下载,因安全策略禁止跨源 `download` 属性;需改用 tauri 官方文件系统插件(如 `@tauri-apps/plugin-fs` 和 `@tauri-apps/plugin-dialog`)实现可控、跨平台的本地文件保存。
在基于 Tauri 构建的桌面应用中,直接复用 Web 端的 <a href="https://www.php.cn/link/263b1243ca2dbeb358777ceabc4a2e4c" download></a> 方式下载远程 Blob(尤其是通过 fetch 获取后动态创建链接)会在 macOS 上失败,并抛出明确错误:
"The download attribute on anchor was ignored because its href URL has a different security origin"
该错误并非 CORS 问题,而是 WebKit(Safari 内核,Tauri 在 macOS 默认使用 WebView2 或 WebKit 后端)对 download 属性的严格限制:仅允许同源 URL 使用 download,而你的 downloadLink 是服务端返回的跨域 URL(如 https://api.example.com/files/123.pdf),即使它可被浏览器直接访问,Tauri 的 WebView 仍会拒绝触发下载。
✅ 正确解法是绕过浏览器下载机制,交由 Tauri 原生能力处理:
- 用
fetch获取响应(推荐response.arrayBuffer()或response.blob()); - 将二进制数据转换为
Uint8Array; - 调用
@tauri-apps/plugin-dialog.save()弹出系统保存对话框,获取用户选定路径; - 使用
@tauri-apps/plugin-fs.writeFile()将数据写入本地磁盘。
以下是推荐的完整实现(适配 PDF、ZIP、图片等任意二进制类型):
import { save } from '@tauri-apps/plugin-dialog';
import { writeFile } from '@tauri-apps/plugin-fs';
async function downloadBlobFromUrl(downloadUrl: string, suggestedName: string): Promise<void> {
try {
const response = await fetch(downloadUrl);
if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
// 推荐:直接读取 ArrayBuffer(比 blob.stream() 更简洁可靠)
const arrayBuffer = await response.arrayBuffer();
const data = new Uint8Array(arrayBuffer);
// 弹出原生保存对话框(支持默认文件名和类型过滤)
const filePath = await save({
defaultPath: suggestedName,
filters: [
{
name: 'All Files',
extensions: ['*']
}
]
});
// 写入文件(自动处理路径权限,无需额外配置)
await writeFile(filePath, data);
console.log('✅ 文件已成功保存至:', filePath);
} catch (err) {
console.error('❌ 下载失败:', err);
alert(`下载失败:${err instanceof Error ? err.message : String(err)}`);
}
}
// 调用示例(替换你原有 fetch 链式调用)
downloadBlobFromUrl(
downloadlinkResponse.some.downloadLink,
downloadlinkResponse.some.name
);</void>
⚠️ 注意事项:
-
不要使用
URL.createObjectURL(blob)+<a></a>点击方案:Tauri 的 WebView 对blob:协议支持不稳定,尤其在 macOS 上易触发DOMException: Failed to execute 'createObjectURL'或静默失败; -
确保已安装并注册插件:运行
pnpm add @tauri-apps/plugin-dialog @tauri-apps/plugin-fs,并在tauri.conf.json的plugins中启用(Tauri v2 默认启用,v1 需手动添加); -
权限声明(仅 Tauri v1):若使用旧版,需在
tauri.conf.json→tauri.allowlist.fs.writeFile设为true; -
大文件优化:对超大文件(>100MB),建议流式分块读取(参考答案中的
blob.stream().getReader()),避免内存溢出,但多数场景arrayBuffer()已足够高效。
总结:Tauri 的核心优势在于“用 Rust 安全地接管敏感操作”。放弃模拟浏览器下载行为,转而使用 plugin-dialog + plugin-fs 组合,不仅能彻底解决 macOS 兼容性问题,还能获得更一致的用户体验(统一对话框、无 MIME 类型限制、支持后台写入),是 Tauri 应用中文件下载的标准实践。











