java.io.IOException: UT010029: Stream is closed
記錄一次項目中的異常钻弄,在做下載文件時灾部,文件雖然能夠?qū)С鰜淼窍到y(tǒng)中卻出現(xiàn)了一堆報錯信息。java.io.IOException: UT010029: Stream is closed
通過報錯信息可以看出這個異常是流被關(guān)閉了,在我們學JAVA基礎(chǔ)時我們知道,使用I/O流時要及時關(guān)閉。但是如果關(guān)閉的不合理也是有問題的扼褪,這個錯誤是由于這個流被關(guān)閉了,而在其他地方又用到了這個流粱栖,所以獲取不到流就會報錯了话浇。
定位到了大概原因,接下來看下我的功能代碼闹究,果然在finally那對輸出流進行了關(guān)閉處理幔崖,由于我對輸出流進行了關(guān)閉操作,這個流是從response中拿到的渣淤,不是自己創(chuàng)建的而我卻將他關(guān)閉了赏寇,Spring MVC框架中可能會使用流進行編碼處理等操作,由于拿不到流從而導(dǎo)致的報錯价认。
public static void exportFile(File zipFile, HttpServletResponse response) throws IOException {
// 輸入流
BufferedInputStream bufferedInputStream = null;
// 輸出流
BufferedOutputStream bufferedOutputStream = null;
try {
response.reset();
//設(shè)置文件ContentType類型
response.setContentType("application/json");
//設(shè)置Content-Disposition嗅定,設(shè)置attachment,瀏覽器會激活文件下載框用踩;filename指定下載后默認保存的文件名
//不設(shè)置Content-Disposition的話渠退,文件會在瀏覽器內(nèi)打開,比如txt脐彩、img文件
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFile.getName(), "UTF-8"));
// 輸入流
bufferedInputStream = new BufferedInputStream(new FileInputStream(zipFile));
// 輸出流
bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
byte[] size = new byte[1024];
int length = 0;
// 2.將文件轉(zhuǎn)換成流碎乃,讀取到內(nèi)存中
while ((length = bufferedInputStream.read(size)) != -1) {
bufferedOutputStream.write(size, 0, length);
}
bufferedOutputStream.flush();
} catch (IOException e) {
log.error(e.getMessage());
throw new RuntimeException(Err_000400010061);
} finally {
// 關(guān)閉輸入流
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
// 使用SpringMVC框架時,在我們的業(yè)務(wù)代碼中處理完業(yè)務(wù)邏輯后惠奸,不要對HttpServletResponse對象的ServletOutputStream做流關(guān)閉處理
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
}
}
將下面這部分代碼去掉后發(fā)現(xiàn)報錯消失了
// 使用SpringMVC框架時梅誓,在我們的業(yè)務(wù)代碼中處理完業(yè)務(wù)邏輯后,不要對HttpServletResponse對象的ServletOutputStream做流關(guān)閉處理
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
小結(jié)
我們在使用I/O流的原則是佛南,如果是自己手動創(chuàng)建的流梗掰,那么我們在使用完后必須將流進行關(guān)閉。如果不是自己創(chuàng)建的流嗅回,我們不需要也不要手動將流進行關(guān)閉及穗,因為框架中可能會用到這些流做一些額外的處理。