HttpURLConnection PUT 到 Google 云存储给出错误 403
HttpURLConnection PUT to Google Cloud Storage giving error 403
我尝试使用 XML API 将文件上传到 Google 云存储。我有正确的 GoogleAccessId、到期日期和为每次上传生成的签名。奇怪的是我可以使用 Postman PUT 文件(Chrome 的应用程序),所以我确定 URL 没问题。我只是无法使用我的 Android Java 程序来放置它(它 returns 对我来说是 403 错误)。执行上传的源代码在这里(它基于这个:https://cloud.google.com/storage/docs/access-control#Signing-Strings):
URL url;
HttpURLConnection connection;
try {
url = new URL("http://google-testbucket.storage.googleapis.com/testdata.txt?GoogleAccessId=1234567890123@developer.gserviceaccount.com&Expires=1331155464&Signature=BClz9e4UA2MRRDX62TPd8sNpUCxVsqUDG3YGPWvPcwN%2BmWBPqwgUYcOSszCPlgWREeF7oPGowkeKk7J4WApzkzxERdOQmAdrvshKSzUHg8Jqp1lw9tbiJfE2ExdOOIoJVmGLoDeAGnfzCd4fTsWcLbal9sFpqXsQI8IQi1493mw%3D");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write("Test");
out.close();
Log.i("TAG", "PUT Response code: " + connection.getResponseCode());
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e("TAG", "MalformedURLException");
} catch (ProtocolException e) {
e.printStackTrace();
Log.e("TAG", "ProtocolException");
} catch (IOException e) {
e.printStackTrace();
Log.e("TAG", "IOException");
}
PUT 对象的文档:https://cloud.google.com/storage/docs/xml-api/put-object-upload
任何人都可以调查这个问题并给我提示这个问题可能出了什么问题吗?
我刚刚发现 HttpURLConnection
添加 Content-Type
header 本身的值为 application/x-www-form-urlencoded
。我在我的 android 模拟器上使用 HTTP 嗅探器完成了它。
这 auto-added header 导致签名不匹配。在我更改 server-side 上的代码以允许使用 Content-Type: application/x-www-form-urlencoded
的请求后,它生成了正确的签名并且工作正常。
感谢@morpheus05 的付出。
请这样设置你的Content-Type
。
connection.setRequestProperty("Content-Type"," ");
因为HttpsUrlConnection
自动生成Content-Type为
"Content-Type: application/x-www-form-urlencoded"
这会导致签名不匹配。
我尝试使用 XML API 将文件上传到 Google 云存储。我有正确的 GoogleAccessId、到期日期和为每次上传生成的签名。奇怪的是我可以使用 Postman PUT 文件(Chrome 的应用程序),所以我确定 URL 没问题。我只是无法使用我的 Android Java 程序来放置它(它 returns 对我来说是 403 错误)。执行上传的源代码在这里(它基于这个:https://cloud.google.com/storage/docs/access-control#Signing-Strings):
URL url;
HttpURLConnection connection;
try {
url = new URL("http://google-testbucket.storage.googleapis.com/testdata.txt?GoogleAccessId=1234567890123@developer.gserviceaccount.com&Expires=1331155464&Signature=BClz9e4UA2MRRDX62TPd8sNpUCxVsqUDG3YGPWvPcwN%2BmWBPqwgUYcOSszCPlgWREeF7oPGowkeKk7J4WApzkzxERdOQmAdrvshKSzUHg8Jqp1lw9tbiJfE2ExdOOIoJVmGLoDeAGnfzCd4fTsWcLbal9sFpqXsQI8IQi1493mw%3D");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write("Test");
out.close();
Log.i("TAG", "PUT Response code: " + connection.getResponseCode());
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e("TAG", "MalformedURLException");
} catch (ProtocolException e) {
e.printStackTrace();
Log.e("TAG", "ProtocolException");
} catch (IOException e) {
e.printStackTrace();
Log.e("TAG", "IOException");
}
PUT 对象的文档:https://cloud.google.com/storage/docs/xml-api/put-object-upload
任何人都可以调查这个问题并给我提示这个问题可能出了什么问题吗?
我刚刚发现 HttpURLConnection
添加 Content-Type
header 本身的值为 application/x-www-form-urlencoded
。我在我的 android 模拟器上使用 HTTP 嗅探器完成了它。
这 auto-added header 导致签名不匹配。在我更改 server-side 上的代码以允许使用 Content-Type: application/x-www-form-urlencoded
的请求后,它生成了正确的签名并且工作正常。
感谢@morpheus05 的付出。
请这样设置你的Content-Type
。
connection.setRequestProperty("Content-Type"," ");
因为HttpsUrlConnection
自动生成Content-Type为
"Content-Type: application/x-www-form-urlencoded"
这会导致签名不匹配。