我正在尝试创建一个签名的 URL 并使用它从我的 PC 将文件上传到谷歌云存储。
我使用 Advanced REST Client(ARC) 作为客户端应用程序。在服务器端,我有一个在 Appengine 上运行的基于球衣的服务器。
我首先从 ARC 发送一个 GET 请求,在接收到该请求后,应用程序引擎会生成一个签名 URL 并将其返回到响应中。
之后,我使用要在正文中上传的文件执行 PUT 请求,并将请求 URL 设置为在对 GET 的响应中收到的内容。
创建签名 URL 的代码片段:
String encodedUrl = null;
String contentMD5 = "";
String contentType = "";
String httpVerb;
httpVerb = "PUT";
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 10);
long expiration = calendar.getTimeInMillis() / 1000L;
String canonicalizedResource = "/" + bucketName + "/" + objectName;
String baseURL = "https://storage.googleapis.com" + canonicalizedResource;
String stringToSign =
httpVerb + "\n" + contentMD5 + "\n" + contentType + "\n" + expiration + "\n"
+ canonicalizedResource;
AppIdentityService service = AppIdentityServiceFactory.getAppIdentityService();
String googleAccessId = service.getServiceAccountName();
SigningResult signingResult = service.signForApp(stringToSign.getBytes());
String encodedSignature = null;
try {
encodedSignature =
new String(Base64.encodeBase64(signingResult.getSignature(), false), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new InternalServerErrorException();
}
String signature = null;
try {
signature = URLEncoder.encode(encodedSignature, "UTF-8").toString();
} catch (UnsupportedEncodingException e) {
throw new InternalServerErrorException();
}
encodedUrl =
baseURL + "?GoogleAccessId=" + googleAccessId + "&Expires=" + expiration
+ "&Signature=" + signature;
System.out.println("Signed URL is: "+encodedUrl);
但是我观察到以下问题:
每当我发送任何文件类型的 PUT 请求时,都会收到以下错误:
错误 - 403
代码 - SignatureDoesNotMatch消息 - 我们计算的请求签名与您提供的签名不匹配。检查您的 Google 密钥和签名方法
请注意,在我的代码中,我在创建要签名的字符串时将内容类型设置为“”。此外,在创建 PUT 请求时,我不包含任何 Content-type 标头。
据我了解,如果我在创建签名 URL 时不将 contentType 包含在 stringToSign 中,并且在发送 PUT 请求时也不将其添加为标头,那应该没问题。那么错误的原因可能是什么?
- 之后,我通过代码更改并在代码中创建 stringToSign 时添加了 contentType,并在发送 PUT 请求时提供了相应的 Content-Type 标头。
在这种情况下,我可以上传文件,但是上传的文件已修改/损坏。我尝试使用 text/plain 和 image/jpeg。
问题是在文件开头添加了以下文本:
------WebKitFormBoundaryZX8rPPhnm1WXPrUf
Content-Disposition: form-data; name="fileUpload5"; filename="blob"
Content-Type: text/plain
我可以在文本文件中看到这一点,并在十六进制编辑器中打开 .jpg 文件。.jpg 无法在标准图像应用程序中打开,因为该文件已被开头的文本损坏
我在这里错过了什么吗?这是高级 REST 客户端中的任何问题吗?实际上,每当我在正文中发送带有某个文件的 PUT 请求时,我都会在 ARC 中收到一条消息,说: 发送请求时,内容类型标头最终将更改为 multipart/form-data 但是,我保存了导出的所有从 ARC 向文件发送消息,但我没有找到任何 Content-type 标头设置为 multipart/form-data 的消息。那么为什么会出现这条消息,它实际上是一个问题吗?