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

如何通过Firebase REST API使用Flutter http包上传文件并获取URL

使用Flutter http包通过Firebase REST API上传文件并获取访问URL

前提准备

  • 你的Firebase项目已启用Cloud Storage服务
  • 记录下存储桶名称(格式:[项目ID].appspot.com,可在Firebase控制台存储页面查看)
  • 确保Cloud Storage安全规则允许上传(测试阶段可临时设为allow read, write: if true;,生产环境需配置严格权限)
  • Flutter项目已集成Firebase Auth(用于获取身份验证的ID Token)

安装依赖

在pubspec.yaml中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  http: ^1.1.0
  firebase_auth: ^4.16.0
  path_provider: ^2.1.1

执行flutter pub get完成安装。

上传步骤及代码实现

1. 获取Firebase ID Token

上传请求需携带ID Token验证身份,通过Firebase Auth获取:

import 'package:firebase_auth/firebase_auth.dart';

Future<String> getIdToken() async {
  User? user = FirebaseAuth.instance.currentUser;
  if (user == null) {
    throw Exception('用户未登录,请先登录');
  }
  return await user.getIdToken();
}

2. 读取本地文件并准备参数

以读取本地文件为例(实际可通过file_picker插件让用户选择文件),同时获取文件的MIME类型:

import 'dart:io';
import 'package:path_provider/path_provider.dart';

// 示例:获取本地文件(替换为实际文件路径或文件选择逻辑)
Future<File> getLocalFile() async {
  Directory appDir = await getApplicationDocumentsDirectory();
  return File('${appDir.path}/test.jpg');
}

// 根据文件后缀判断MIME类型
String getMimeType(String filePath) {
  if (filePath.endsWith('.jpg') || filePath.endsWith('.jpeg')) {
    return 'image/jpeg';
  } else if (filePath.endsWith('.pdf')) {
    return 'application/pdf';
  } else if (filePath.endsWith('.mp3')) {
    return 'audio/mpeg';
  } else if (filePath.endsWith('.mp4')) {
    return 'video/mp4';
  }
  return 'application/octet-stream'; // 默认二进制类型
}

3. 发送上传请求并生成访问URL

使用http包发送POST请求完成上传,从响应中提取令牌并拼接访问URL:

import 'package:http/http.dart' as http;
import 'dart:convert';

Future<String> uploadFileToFirebase() async {
  try {
    File file = await getLocalFile();
    String fileName = file.path.split('/').last;
    String storagePath = 'user_uploads/$fileName'; // 文件在Firebase存储中的路径
    String mimeType = getMimeType(file.path);
    String idToken = await getIdToken();

    // 构建上传请求URL,注意对存储路径进行URL编码
    String uploadEndpoint = 'https://firebasestorage.googleapis.com/v0/b/[你的存储桶名称]/o?name=${Uri.encodeComponent(storagePath)}';

    // 读取文件字节数据
    List<int> fileBytes = await file.readAsBytes();

    // 发送上传请求
    http.Response response = await http.post(
      Uri.parse(uploadEndpoint),
      headers: {
        'Authorization': 'Bearer $idToken',
        'Content-Type': mimeType,
      },
      body: fileBytes,
    );

    if (response.statusCode == 200) {
      // 解析响应获取下载令牌
      Map<String, dynamic> responseData = jsonDecode(response.body);
      String downloadToken = responseData['downloadTokens'];

      // 拼接可直接访问的文件URL
      String accessUrl = 'https://firebasestorage.googleapis.com/v0/b/[你的存储桶名称]/o/${Uri.encodeComponent(storagePath)}?alt=media&token=$downloadToken';
      return accessUrl;
    } else {
      throw Exception('上传失败:${response.statusCode} - ${response.body}');
    }
  } catch (e) {
    throw Exception('上传出错:$e');
  }
}

注意事项

  • 替换代码中的[你的存储桶名称]为实际的Firebase存储桶名称
  • 大于10MB的文件建议使用分块上传,避免请求超时
  • 生产环境必须修改Cloud Storage安全规则,限制上传权限(比如仅允许已登录用户上传、限制文件类型/大小)
  • 可集成file_picker插件实现用户选择本地文件的功能,替代示例中的固定路径逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 21:30:51