如何通过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
相关产品推荐
相关产品推荐

