如何将 ResponseBody(在我的例子中是 PDF)写入外部存储? java.lang.IllegalStateException 的问题:关闭
How to write ResponseBody (in my case PDF) to external storage? Problem with java.lang.IllegalStateException: closed
我想将 ResponseBody 写入外部存储(下载文件夹)。直到一周前,一切都运行良好,然后我需要 更新 okhttp3 版本 现在当我 运行 我的应用程序时,发生了以下情况之一:
这是我的改造:
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(link)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(create())
.client(client)
.build();
这是我将ResponseBody写入ES的函数:
private boolean writeResponseBodyToDisk(ResponseBody body) {
File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "test.pdf");
try {
InputStream fis = body.byteStream();
long length = body.bytes().length;
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fis.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
OutputStream op = new FileOutputStream(dir);
op.write(bytes);
} catch (Exception ex) {
Toast.makeText(MainActivity.this, ex.getMessage().toString(), Toast.LENGTH_LONG);
}
return true;
}
当我这样放置这部分时:
long length = body.bytes().length;
我得到这个异常:
java.lang.IllegalStateException: closed
但是当我离开时它就像版本更新之前一样:
long length = body.contentLength();
然后什么也没有发生。在我更新 okhttp3 的版本之前,这种方式一直有效。
我知道我不能将第一个选项与 bytes.length 一起使用,但我不知道任何替代方法。
只需更改输出流的初始化
OutputStream op;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
ContentValues values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DISPLAY_NAME,"test.pdf");
values.put(MediaStore.Files.FileColumns.MIME_TYPE,"application/pdf");
values.put(MediaStore.Files.FileColumns.RELATIVE_PATH,Environment.DIRECTORY_DOWNLOADS);
Uri fileUri = getContentResolver().insert(
MediaStore.Files.getContentUri("external"),
values
);
try {
op = getContentResolver().openOutputStream(fileUri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}else{
File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "test.pdf");
try {
op = new FileOutputStream(dir);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
try {
InputStream fis = body.byteStream();
long length = body.bytes().length;
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fis.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
op.write(bytes);
} catch (Exception ex) {
Toast.makeText(MainActivity.this, ex.getMessage().toString(), Toast.LENGTH_LONG);
}
我想将 ResponseBody 写入外部存储(下载文件夹)。直到一周前,一切都运行良好,然后我需要 更新 okhttp3 版本 现在当我 运行 我的应用程序时,发生了以下情况之一:
这是我的改造:
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(link)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(create())
.client(client)
.build();
这是我将ResponseBody写入ES的函数:
private boolean writeResponseBodyToDisk(ResponseBody body) {
File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "test.pdf");
try {
InputStream fis = body.byteStream();
long length = body.bytes().length;
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fis.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
OutputStream op = new FileOutputStream(dir);
op.write(bytes);
} catch (Exception ex) {
Toast.makeText(MainActivity.this, ex.getMessage().toString(), Toast.LENGTH_LONG);
}
return true;
}
当我这样放置这部分时:
long length = body.bytes().length;
我得到这个异常:
java.lang.IllegalStateException: closed
但是当我离开时它就像版本更新之前一样:
long length = body.contentLength();
然后什么也没有发生。在我更新 okhttp3 的版本之前,这种方式一直有效。
我知道我不能将第一个选项与 bytes.length 一起使用,但我不知道任何替代方法。
只需更改输出流的初始化
OutputStream op;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
ContentValues values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DISPLAY_NAME,"test.pdf");
values.put(MediaStore.Files.FileColumns.MIME_TYPE,"application/pdf");
values.put(MediaStore.Files.FileColumns.RELATIVE_PATH,Environment.DIRECTORY_DOWNLOADS);
Uri fileUri = getContentResolver().insert(
MediaStore.Files.getContentUri("external"),
values
);
try {
op = getContentResolver().openOutputStream(fileUri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}else{
File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "test.pdf");
try {
op = new FileOutputStream(dir);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
try {
InputStream fis = body.byteStream();
long length = body.bytes().length;
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fis.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
op.write(bytes);
} catch (Exception ex) {
Toast.makeText(MainActivity.this, ex.getMessage().toString(), Toast.LENGTH_LONG);
}