HttpURLConnection PUT для Google Cloud Storage, дающий ошибку 403
Я попытался загрузить файл в Google Cloud Storage с помощью XML API. У меня есть правильный GoogleAccessId, дата истечения срока действия и подпись, сгенерированная для каждой загрузки. Странно, что я могу PUT файл использовать Postman (приложение для Chrome), поэтому я уверен, что URL-адрес в порядке. Я просто не могу использовать его с помощью моей программы Android Java (она возвращает мне ошибку 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/[email protected]unt.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
Может кто-нибудь заглянуть в эту проблему и дать мне подсказки, что могло бы пойти не так с этим?
Ответы
Ответ 1
Я только что понял, что HttpURLConnection
добавляет заголовок Content-Type
со значением application/x-www-form-urlencoded
сам по себе. Я сделал это, используя HTTP-сниффер на моем эмуляторе Android.
Этот заголовок с автоматическим добавлением вызвал несоответствие подписи. После того, как я изменил код на стороне сервера, чтобы разрешить запросы с помощью Content-Type: application/x-www-form-urlencoded
, он генерирует правильную подпись и отлично работает.
Спасибо @morpheus05 за ваше обязательство.
Ответ 2
Пожалуйста, установите ваш Content-Type
следующим образом.
connection.setRequestProperty("Content-Type"," ");
Потому что HttpsUrlConnection
автоматически генерирует Content-Type как
"Content-Type: application/x-www-form-urlencoded"
это приведет к несоответствию подписи.