如何解决HTTP消息未正确加载Android
我想用volley加载json并使用BufferedInputStream
下载图像。由于这些请求是针对非加密HTTP端口上的LAN ip地址发出的,因此我启用了android:usesCleartextTraffic="true"
我从Volley得到这个错误:
com.android.volley.ParseError: org.json.JSONException: Unterminated object at character 20 of {"data":{"foo":"bar"
我这样使用BufferedInputStream
:
private boolean getFileFromUrl(String url,String path) {
try (BufferedInputStream in = new BufferedInputStream(new URL(url).openStream());
FileOutputStream fileOutputStream = new FileOutputStream(path)) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer,1024)) != -1) {
fileOutputStream.write(dataBuffer,bytesRead);
}
fileOutputStream.close();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
如果我在服务器上提供一个Content-Length
参数,有时会出现此错误:
W/System.err: java.net.ProtocolException: unexpected end of stream
at com.android.okhttp.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:398)
at com.android.okhttp.okio.RealBufferedSource$1.read(RealBufferedSource.java:372)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:248)
W/System.err: at java.io.BufferedInputStream.read1(BufferedInputStream.java:288)
W/System.err: at java.io.BufferedInputStream.read(BufferedInputStream.java:347)
如果没有Content-Length
参数,则某些文件仍未完全加载。没有抛出IOException
,但是如果我尝试读取某些图像,则会出现此错误:
<Corrupt JPEG data: premature end of data segment> from output_message
这些错误是随机发生的。如果使用浏览器打开这些网址,则可以完美加载它们。我不知道如何调试它。
我使用getFileFromUrl
网址尝试了https
,然后一切正常。不幸的是,我无法在该项目中使用https,只能使用http。
修改
我用一个线程创建了一个执行服务,然后在getFileFromUrl
实例中提交了Runnable
调用,但是仍然出现错误:
Executors.newFixedThreadPool(1);
解决方法
看起来,API(或OkHttp客户端)由于某种原因会截断响应正文。
OkHttp客户端的读取超时很短(可以提高该值),或者API没有及时响应(或作为整个JSON响应)。当它始终在网络浏览器中正确响应时,确实应该是(n Android)客户端问题。解决此问题的一种方法可能是捕获ProtocolException
,删除中止的下载,然后重试再次下载文件。
但是我假设Content-Length
标头的值可能完全是错误的。
我的意思是,如果不手动设置此值,则可以正确计算该值。
客户只能在收到错误指令后采取异常行动。
Content-Length
告诉客户端接收缓冲区必须有多大...
即使响应没有被截断,客户端也会拒绝多余的响应。
例如:
Content-Length: 20
...显然是API报告的内容。
{"data":{"foo":"bar"
Content-Length: 22
...是API应该报告的内容。
{"data":{"foo":"bar"}}
,
在您的代码中,您仅使用http
打开原始OpenConnection
连接。但是,我不确定加载图像的正确(简单)方法。您可以使用任何其他库来加载图像,这会注意内容长度和标题。
- 仅适用于
Glide
。
Glide.with(context)
.asBitmap()
.load(url)
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource,@Nullable Transition<? super Bitmap> transition) {
// do whatever you want with bitmap
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
- 要保存,只需在或上方使用您的代码即可。
public void write(String fileName,Bitmap bitmap) {
try (FileOutputStream out = new FileOutputStream(filename)) {
bmp.compress(Bitmap.CompressFormat.PNG,100,out); // bmp is your Bitmap
instance
// PNG is a lossless format,the compression factor (100) is ignored
} catch (IOException e) {
e.printStackTrace();
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。