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

Flutter Web:将GCS公开URL文件下载至本地下载文件夹的实现

Flutter Web实现GCS公开文件直接下载到本地文件夹

因为是Web应用,没法像原生那样直接操作本地文件系统,得借助浏览器的下载机制来实现。下面是具体的实现步骤,兼容Windows、iOS、Linux的主流浏览器:

核心思路

通过HTTP请求获取GCS文件的字节数据,转为浏览器可识别的Blob对象,再创建隐藏的下载链接触发浏览器的下载流程,最后清理资源。

实现步骤

  1. 添加依赖
    在pubspec.yaml里加入http包,用来发起HTTP请求获取文件数据:

    dependencies:
      flutter:
        sdk: flutter
      http: ^1.1.0 # 可替换为最新版本
    
  2. 封装下载函数
    创建一个可复用的下载函数,处理从请求到触发下载的全部逻辑:

    import 'dart:html' as html;
    import 'dart:typed_data';
    import 'package:http/http.dart' as http;
    import 'package:flutter/material.dart';
    
    Future<void> downloadGcsFile(String gcsUrl, String fileName) async {
      try {
        // 发起请求获取文件字节数据
        final response = await http.get(Uri.parse(gcsUrl));
        if (response.statusCode != 200) {
          throw Exception('文件获取失败,状态码:${response.statusCode}');
        }
    
        // 将字节数据转为Blob(可指定MIME类型,提升兼容性)
        final blob = html.Blob(
          [response.bodyBytes],
          _getMimeTypeFromUrl(gcsUrl), // 可选,自动识别文件类型
        );
        // 创建Blob的临时URL
        final blobUrl = html.Url.createObjectUrlFromBlob(blob);
    
        // 创建隐藏的a标签,设置下载属性
        final downloadAnchor = html.AnchorElement(href: blobUrl)
          ..setAttribute('download', fileName)
          ..style.display = 'none';
    
        // 添加到DOM并触发点击
        html.document.body?.append(downloadAnchor);
        downloadAnchor.click();
    
        // 清理资源,避免内存泄漏
        html.document.body?.remove(downloadAnchor);
        html.Url.revokeObjectUrl(blobUrl);
    
        // 可选:显示下载成功提示
        ScaffoldMessenger.of(html.window.navigator.key.currentContext!)
            .showSnackBar(const SnackBar(content: Text('文件开始下载')));
      } catch (e) {
        print('下载出错:$e');
        // 显示错误提示
        ScaffoldMessenger.of(html.window.navigator.key.currentContext!)
            .showSnackBar(SnackBar(content: Text('下载失败:$e')));
      }
    }
    
    // 辅助函数:从URL提取MIME类型
    String _getMimeTypeFromUrl(String url) {
      final extension = url.split('.').last.toLowerCase();
      switch (extension) {
        case 'pdf':
          return 'application/pdf';
        case 'jpg':
        case 'jpeg':
          return 'image/jpeg';
        case 'png':
          return 'image/png';
        case 'txt':
          return 'text/plain';
        default:
          return 'application/octet-stream';
      }
    }
    
  3. 在按钮中调用
    替换原来的launchUrl,直接调用上面的函数:

    ElevatedButton(
      onPressed: () {
        // 替换为你的GCS公开URL和想要的文件名
        const gcsFileUrl = 'https://storage.googleapis.com/your-bucket/your-file.pdf';
        downloadGcsFile(gcsFileUrl, '我的文件.pdf');
      },
      child: const Text('下载文件'),
    )
    

关键注意事项

  • CORS配置:如果浏览器报跨域错误,需要给你的GCS桶配置CORS规则,允许Web应用的域名发起GET请求。示例CORS配置(在GCS控制台或通过gsutil命令设置):
    [
      {
        "origin": ["https://your-web-app-domain.com"], // 替换为你的Web域名,生产环境不要用*
        "method": ["GET"],
        "responseHeader": ["Content-Type"],
        "maxAgeSeconds": 3600
      }
    ]
    
  • 浏览器兼容性:主流浏览器(Chrome、Firefox、Safari、Edge)都支持这个方法,iOS Safari需确保Blob的MIME类型正确,避免无法识别文件。
  • 资源清理:一定要调用Url.revokeObjectUrl释放临时URL,否则会造成内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:47:35