JAVA POI 엑셀파일 생성시, "이 통합 문서의 내용을 복구하시겠습니까?" 에러해결

반응형
728x90
반응형

에러 발생

Poi 라이브러리를 사용하여 엑셀 다운로드 개발을 하는 도중, 다운로드된 파일을 열때마다 에러가 발생하였다.

 

[파일명]에 읽을 수 없는 내용이 있습니다. 이 통합 문서의 내용을 복구하시겠습니까? 이 통합 문서의 원본을 신뢰할 수 있는 경우 [예]를 클릭하십시오. 

 

이 상태로 [예]를 누르게 되면 파일이 열리면서 아래 메세지가 적힌 팝업이 뜹니다

 

[파일명.xlsx](으)로 복구

읽을 수 없는 내용을 복구하거나 제거하여 파일을 열 수 있습니다.

 

[복구] 버튼을 누르면 엑셀파일은 알맞게 생성되었지만 열때마다 뜨는 경고창을 해결해야했다.

 

 

해결

Before

  response.setHeader("Set-Cookie", "fileDownload=true; path=/");   response.setHeader("Content-Disposition", String.format("attachment; filename=" + excelName));      response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");   wb.write(response.getOutputStream());

 

내가 처음 사용했던 위 코드에서 단지 OutputStream을 close 해주지 않았기 때문이였다. response.getOutputStream().close() 한줄 때문에 엑셀 파일에서 내용을 손실했다는 에러가 발생한 것이였다.

 

After

  ByteArrayOutputStream bout = new ByteArrayOutputStream();   wb.write(bout);   bout.close();    response.setHeader("Set-Cookie", "fileDownload=true; path=/");   response.setHeader("Content-Disposition", "attachment; filename=" + excelName);   response.setContentLength(bout.size());    ServletOutputStream out = response.getOutputStream();    out.write(bout.toByteArray());   out.flush();   out.close();

 

 

After 코드로 수정 후, 수행결과 에러는 해결되었다. 하지만 After 코드에도 문제는 있었다.

 

ByteArrayOutputStream 을 생성하고, wb.write(bout)로 해당 스트림에 wb객체 (엑셀파일)을 write한다.

(여기서, WorkBook 객체 wb의 write 메소드는 wb 객체에 쓰는게 아닌, bout 안에 자신을 쓴다는 뜻이다. = write out)그리고 다시한번 ServletOutputStream 을 생성하여 ByteArrayOutputStream 스트림 안의 내용을 wirte 한다.

 

위 코드는 Stream을 굳이 2번 생성한 것이다.

 

1. ByteArrayOutputStream을 선언하고,
2. ByteArrayOutputStream스트림에 WorkBook 객체 wb를 쓰고, 
3. 또다시 ServletOutputStream을 선언하고, --> Stream 2번 생성
4. 해당 스트림에 ByteArrayOutputStream 의 객체를 toByteArray 메소드를 사용하하여 write 한것이다.

 

 

마무리

스트림 사용 이후, close() 메소드를 호출하는 것은 당연시 되어야한다. 그리고 위 예제에서는 flush() 메소드 호출 후 close() 메소드를 호출하지만 close() 메소드만 호출해도 flush()는 함께 호출됨을 알아두자.

 

 

 

반응형

Designed by JB FACTORY