Flutter Desktop用Firebase Storage REST API传图片报Invalid Credentials错误
解决Firebase Storage REST API上传401认证错误
问题分析与修复步骤
1. Authorization头格式错误
你的代码中Authorization头末尾多了一个逗号:
"Authorization": "Bearer $token,"
这个多余的逗号会导致令牌格式无效,Firebase无法正确解析,必须删除逗号,改为:
"Authorization": "Bearer $token"
2. 请求数据错误
当前data参数传入的是文件路径字符串,而Firebase Storage的media上传需要直接传入文件的二进制数据。你需要读取文件字节后传入:
final fileBytes = await File(filePath).readAsBytes(); // ... data: fileBytes,
3. Token获取方式错误
FirebaseAuth.instance.tokenProvider.idToken是一个Stream<String>,直接await无法正确获取令牌值。正确的方式是通过当前认证用户获取ID Token:
final user = FirebaseAuth.instance.currentUser; if (user == null) { // 处理未登录情况 throw Exception("User not authenticated"); } final token = await user.getIdToken(true); // true表示强制刷新令牌,确保有效性
修正后的完整代码
Future<void> uploadProfilePicture({ required String fileName, required String filePath, required String email, }) async { return Chain.capture(() async { final url = "https://storage.googleapis.com/upload/storage/v1/b/${Constants.projectID}.appspot.com/o?uploadType=media&name=$email/profilePicture/$fileName"; final fileBytes = await File(filePath).readAsBytes(); final user = FirebaseAuth.instance.currentUser; if (user == null) { throw Exception("User not authenticated"); } final token = await user.getIdToken(true); try { final response = await _dio.post<Map<String, dynamic>>( url, data: fileBytes, options: Options( headers: { "Content-Type": "image/jpeg", "Authorization": "Bearer $token", }, ), ); logger.i(response.data); } on DioException catch (e, stackTrace) { final terseStacktrace = Chain.forTrace(stackTrace).terse; logger ..e("Failed to upload profile picture", [e, terseStacktrace]) ..e("Error ${e.error} Message ${e.message} Response ${e.response}"); } catch (e, stackTrace) { final terseStacktrace = Chain.forTrace(stackTrace).terse; logger.wtf("Failed to upload profile picture", [e, terseStacktrace]); rethrow; } }); }
额外验证步骤
- 获取有效令牌后,用curl测试是否能正常上传:
curl -X POST --data-binary @/path/to/your/image.jpg \ -H "Authorization: Bearer YOUR_ACTUAL_TOKEN" \ -H "Content-Type: image/jpeg" \ "https://storage.googleapis.com/upload/storage/v1/b/YOUR_BUCKET_NAME/o?uploadType=media&name=test/profilePicture/test.jpg"
如果curl能成功,说明令牌有效,问题出在原Dio代码的实现上。
- 你的Storage规则已配置为允许所有读写操作,因此规则不是认证错误的原因。
内容的提问来源于stack exchange,提问作者Nana Kwame
相关产品推荐
相关产品推荐

