通过 Postman 工作,但不能在 Flutter 中工作:API 使用 GCS pre-signed URL 调用
Works via Postman but not in Flutter: API call with GCS pre-signed URL
我正在尝试使用 pre-signed url 将视频文件上传到 GCS。我已经通过 Google 成功地创建了 url 但现在我在使用它时遇到了问题。
在 Postman 中上传作品,得到响应 200。
postman body, postman params
从 Postman 复制的代码导致 403 Forbidden (SignatureDoesNotMatch):
Future<http.StreamedResponse> uploadVideo(
{required String uploadURL, required String filePath}) async {
var headers = {'Content-Type': 'application/octet-stream'};
var request = http.MultipartRequest('PUT', Uri.parse(uploadURL));
request.files.add(await http.MultipartFile.fromPath('file', filePath));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
} else {
print(response.reasonPhrase);
}
return response;
}
这是我从 Google:
得到的错误
<?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message><StringToSign>GOOG4-RSA-SHA256
20210803T082850Z
20210803/auto/storage/goog4_request
6d513846a3db49f949b0d2eea8f04b90f918b3b94588c3ed55ed3620b7d7e1f6</StringToSign><CanonicalRequest>PUT
/phonedo-interviews/app-test/007/2.mp4
X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=interviews%40interviews-317011.iam.gserviceaccount.com%2F20210803%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20210803T082850Z&X-Goog-Expires=900&X-Goog-SignedHeaders=content-type%3Bhost
content-type:multipart/form-data; boundary=dart-http-boundary-6w1yq6BQN3EkGBrhHZnwidOXZsBecsgSwTT3nBjB9vQCToHt0cg
host:storage.googleapis.com
content-type;host
UNSIGNED-PAYLOAD</CanonicalRequest></Error>
注意:我需要 Content-Type
为 application/octet-stream
,所以我在 Postman 的自动 header 中禁用了 header 并手动添加了 Content-Type
。当我不这样做时,我也得到了 403。
在您的 Postman headers 中,Token
被赋予 GCS(第一行)。鉴于您需要授权,Postman 可能将此 Token 保存在某处 application-wise.
在此 flutter 代码中,您提供的 headers 不包含 Auth 令牌,因此您收到 403 错误。
解决方案是以二进制形式发送文件。
这是工作代码:
Future<http.Response> uploadVideo(
{required String uploadURL, required String filePath}) async {
var response = await http.put(
Uri.parse(uploadURL),
headers: {'content-type': 'application/octet-stream'},
body: File(filePath).readAsBytesSync(),
);
我正在尝试使用 pre-signed url 将视频文件上传到 GCS。我已经通过 Google 成功地创建了 url 但现在我在使用它时遇到了问题。
在 Postman 中上传作品,得到响应 200。
从 Postman 复制的代码导致 403 Forbidden (SignatureDoesNotMatch):
Future<http.StreamedResponse> uploadVideo(
{required String uploadURL, required String filePath}) async {
var headers = {'Content-Type': 'application/octet-stream'};
var request = http.MultipartRequest('PUT', Uri.parse(uploadURL));
request.files.add(await http.MultipartFile.fromPath('file', filePath));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
} else {
print(response.reasonPhrase);
}
return response;
}
这是我从 Google:
得到的错误<?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message><StringToSign>GOOG4-RSA-SHA256
20210803T082850Z
20210803/auto/storage/goog4_request
6d513846a3db49f949b0d2eea8f04b90f918b3b94588c3ed55ed3620b7d7e1f6</StringToSign><CanonicalRequest>PUT
/phonedo-interviews/app-test/007/2.mp4
X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=interviews%40interviews-317011.iam.gserviceaccount.com%2F20210803%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20210803T082850Z&X-Goog-Expires=900&X-Goog-SignedHeaders=content-type%3Bhost
content-type:multipart/form-data; boundary=dart-http-boundary-6w1yq6BQN3EkGBrhHZnwidOXZsBecsgSwTT3nBjB9vQCToHt0cg
host:storage.googleapis.com
content-type;host
UNSIGNED-PAYLOAD</CanonicalRequest></Error>
注意:我需要 Content-Type
为 application/octet-stream
,所以我在 Postman 的自动 header 中禁用了 header 并手动添加了 Content-Type
。当我不这样做时,我也得到了 403。
在您的 Postman headers 中,Token
被赋予 GCS(第一行)。鉴于您需要授权,Postman 可能将此 Token 保存在某处 application-wise.
在此 flutter 代码中,您提供的 headers 不包含 Auth 令牌,因此您收到 403 错误。
解决方案是以二进制形式发送文件。
这是工作代码:
Future<http.Response> uploadVideo(
{required String uploadURL, required String filePath}) async {
var response = await http.put(
Uri.parse(uploadURL),
headers: {'content-type': 'application/octet-stream'},
body: File(filePath).readAsBytesSync(),
);