英文:
Sending Bitmap to Server (B2) via POST not working OKhttpClient HttpURLConnection
问题
以下是您提供的内容的翻译:
我在我的 iOS 应用程序(Swift 5)中使用 Backblaze 成功上传文件(图像和视频)到我的存储桶中,但是在我的 Java Android 应用程序中无法实现。
我收到了正确的授权令牌、下载 URL、上传 URL 和 API URL。
但是当我尝试将数据发布到该 URL 时,它无法正常工作,并且我收到以下错误:
W/OkHttpClient: 对 https://googleads.g.doubleclick.net/ 的连接泄漏。您是否忘记关闭响应体?
D/yyyy enclosed: saveImgToStorage: buffer(com.android.okhttp.internal.http.Http1xStream$FixedLengthSource@e5232ab).inputStream()
saveImgToStorage: 401
W/System.err: java.net.ProtocolException: 在读取响应后无法编写请求正文
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:264)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(Unknown Source:0)
at com.flax.de.Helper.StorageService.saveImgToStorage(StorageService.java:192)
at com.flax.de.Helper.StorageService.getUploadUrl(StorageService.java:142)
at com.flax.de.Helper.StorageService.getAuthData(StorageService.java:95)
W/System.err: at com.flax.de.Categories.NewPostFragment$3.run(NewPostFragment.java:341)
at java.lang.Thread.run(Thread.java:764)
尝试将数据发布到上传 URL 的函数如下所示:
static private void saveImgToStorage(Context context, String id, String uploadUrl, String uploadAuthorizationToken
, String downloadUrl, Uri imageUrl, String bucketName, Interfaces.OnSuccessHashMap onSuccess
, Interfaces.OnError onError) throws IOException {
String photoUrl = downloadUrl+"/file/"+bucketName+"/"+id;
HashMap hashMap = new HashMap();
hashMap.put(API.databaseStrings.URL, photoUrl);
Bitmap bmp = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageUrl);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] fileData = baos.toByteArray();
String contentType = "image/jpg";
String sha1 = "do_not_verify";
HttpURLConnection connection = null;
try {
URL url = new URL(uploadUrl);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", uploadAuthorizationToken);
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestProperty("X-Bz-File-Name", id);
connection.setRequestProperty("X-Bz-Content-Sha1", sha1);
connection.setDoOutput(true);
Log.d("yyyy enclosed", "saveImgToStorage: " + connection.getErrorStream().toString());
Log.d("yyyy enclosed", "saveImgToStorage: " + connection.getResponseCode());
DataOutputStream writer = new DataOutputStream(connection.getOutputStream());
writer.write(fileData);
String jsonResponse = myInputStreamReader(connection.getInputStream());
JSONObject obj = new JSONObject(jsonResponse);
System.out.println(jsonResponse);
} catch (Exception e) {
e.printStackTrace();
onError.onError();
} finally {
connection.disconnect();
}
}
错误代码如下:
401
我不知道为什么它不起作用。正如我所说,它在我的 iOS 设备上运行得非常好,它基本上使用相同的代码,只是用 Swift 编写(从 Backblaze 的指南中获取)。
我个人认为这不是来自 Backblaze 的问题,而是我的请求有问题?
还是我的位图格式有问题?
或者也许我必须异步地执行它?我之前尝试过在主线程之外使用线程,但也没有奏效。
W/System.err: java.io.FileNotFoundException: https://pod-000-1070-11.backblaze.com/b2api/v2/b2_upload_file/afec4cd53b2f323f715a0c18/c000_v0001070_t0002
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:251)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:210)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(Unknown Source:0)
如果使用此代码,我会收到上述内容。
String photoUrl = downloadUrl+"/file/"+bucketName+"/"+id;
HashMap hashMap = new HashMap();
hashMap.put(API.databaseStrings.URL, photoUrl);
Bitmap bmp = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageUrl);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] fileData = baos.toByteArray();
String contentType = "image/jpg";
String sha1 = "do_not_verify";
HttpURLConnection connection = null;
String json = null;
try {
URL url = new URL(uploadUrl);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", uploadAuthorizationToken);
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestProperty("X-Bz-File-Name", id);
connection.setRequestProperty("X-Bz-Content-Sha1", sha1);
connection.setDoOutput(true);
DataOutputStream writer = new DataOutputStream(connection.getOutputStream());
writer.write(fileData);
String jsonResponse = myInputStreamReader(connection.getInputStream());
System.out.println(jsonResponse);
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.disconnect();
}
英文:
I am using Backblaze and managed to upload files (images and videos) to my buckets in my iOS App (swift 5) but I am unable to do so in my java android app.
I receive the correct auth token, download url, upload url and API Url.
But when I try to post it to that url its not working and I receive the following error
W/OkHttpClient: A connection to https://googleads.g.doubleclick.net/ was leaked. Did you forget to close a response body?
D/yyyy enclosed: saveImgToStorage: buffer(com.android.okhttp.internal.http.Http1xStream$FixedLengthSource@e5232ab).inputStream()
saveImgToStorage: 401
W/System.err: java.net.ProtocolException: cannot write request body after response has been read
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:264)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(Unknown Source:0)
at com.flax.de.Helper.StorageService.saveImgToStorage(StorageService.java:192)
at com.flax.de.Helper.StorageService.getUploadUrl(StorageService.java:142)
at com.flax.de.Helper.StorageService.getAuthData(StorageService.java:95)
W/System.err: at com.flax.de.Categories.NewPostFragment$3.run(NewPostFragment.java:341)
at java.lang.Thread.run(Thread.java:764)
The function trying to post the data to the upload url is the following
static private void saveImgToStorage(Context context, String id, String uploadUrl, String uploadAuthorizationToken
, String downloadUrl, Uri imageUrl, String bucketName, Interfaces.OnSuccessHashMap onSuccess
, Interfaces.OnError onError) throws IOException {
String photoUrl = downloadUrl+"/file/"+bucketName+"/"+id;
HashMap hashMap = new HashMap();
hashMap.put(API.databaseStrings.URL, photoUrl);
Bitmap bmp = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageUrl);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] fileData = baos.toByteArray();
String contentType = "image/jpg";
String sha1 = "do_not_verify";
HttpURLConnection connection = null;
try {
URL url = new URL(uploadUrl);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", uploadAuthorizationToken);
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestProperty("X-Bz-File-Name", id);
connection.setRequestProperty("X-Bz-Content-Sha1", sha1);
connection.setDoOutput(true);
Log.d("yyyy enclosed", "saveImgToStorage: " + connection.getErrorStream().toString());
Log.d("yyyy enclosed", "saveImgToStorage: " + connection.getResponseCode());
DataOutputStream writer = new DataOutputStream(connection.getOutputStream());
writer.write(fileData);
String jsonResponse = myInputStreamReader(connection.getInputStream());
JSONObject obj = new JSONObject(jsonResponse);
System.out.println(jsonResponse);
} catch (Exception e) {
e.printStackTrace();
onError.onError();
} finally {
connection.disconnect();
}
}
Error code is as you see
> 401
I have no idea why its not working.
As I said it is working perfectly fine on my iOS devices which uses basically the same code only written in swift (taken from the guide from back blaze)
I personally think its not an issue from back blaze but rather that my request is wrong?
Or the format of my bitmap?
Or maybe I have to do it asynchronously? I tried it with a thread before move it out from the main thread but it did not work either.
W/System.err: java.io.FileNotFoundException: https://pod-000-1070-11.backblaze.com/b2api/v2/b2_upload_file/afec4cd53b2f323f715a0c18/c000_v0001070_t0002
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:251)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:210)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(Unknown Source:0)
is what I receive if use this code
String photoUrl = downloadUrl+"/file/"+bucketName+"/"+id;
HashMap hashMap = new HashMap();
hashMap.put(API.databaseStrings.URL, photoUrl);
Bitmap bmp = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageUrl);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] fileData = baos.toByteArray();
String contentType = "image/jpg";
String sha1 = "do_not_verify";
HttpURLConnection connection = null;
String json = null;
try {
URL url = new URL(uploadUrl);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", uploadAuthorizationToken);
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestProperty("X-Bz-File-Name", id);
connection.setRequestProperty("X-Bz-Content-Sha1", sha1);
connection.setDoOutput(true);
DataOutputStream writer = new DataOutputStream(connection.getOutputStream());
writer.write(fileData);
String jsonResponse = myInputStreamReader(connection.getInputStream());
System.out.println(jsonResponse);
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.disconnect();
}
答案1
得分: 1
第一个版本的函数中存在问题的是这两行代码:
Log.d("yyyy enclosed", "saveImgToStorage: " + connection.getErrorStream().toString());
Log.d("yyyy enclosed", "saveImgToStorage: " + connection.getResponseCode());
getErrorStream()
和 getResponseCode()
都会导致请求被发送,并且从服务器读取响应,因为你要求获取服务器的错误响应和响应码。connection.getOutputStream()
抛出错误,因为此时发送请求正已经太晚了。
你应该删除这些行,或者将它们移动到以下这行代码之后:
writer.write(fileData);
HttpURLConnection
在隐式发送请求方面存在设计上的问题,当你尝试读取响应时它会自动发送请求。
英文:
The issue in the first version of the function is these two lines:
Log.d("yyyy enclosed", "saveImgToStorage: " + connection.getErrorStream().toString());
Log.d("yyyy enclosed", "saveImgToStorage: " + connection.getResponseCode());
Both getErrorStream()
and getResponseCode()
cause the request to be sent, and the response to be read, since you've asked for the error response and response code from the server. connection.getOutputStream()
throws an error because it's too late to send the request body.
You should remove these lines, or move them after the line:
writer.write(fileData);
HttpURLConnection
is 'broken by design' in the way that it implicitly sends the request when you try to read the response.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论