Web

Apache struts 프로젝트에서 servlet으로 pdf 파일 읽기

TheCar 2022. 7. 27. 16:45
728x90
반응형

이번 글은 제목부터 보이듯이 조건이 많아 상당히 머리가 아팠다.

일단 현재 진행하고 있는 프로젝트가 Apache struts라는 태어나 처음 본 framework였고(Spring framework가 너무 익숙하다.)

pdf파일 view 또한 처음 진행 해봤다.

 

그리고 대망의 servlet... 얘는 아직도 잘 모르겠다.

 

시작해보자...

 

우선 파일 다운로드와 같이 a 태그에서 javascript를 호출하여 form을 전송하는 방식이었다.

 

- html

<a href="#" class="id_ok" onclick="pdfView('saveFileName'); return false;">읽기</a>

 

- javascript

function pdfView(saveFileName) {
   let form = document.getElementById("thisForm");
   let tmpFormTarget = form.target;
   //form.target = "_blank"; 사용하면 웹브라우저 새창에서 열린다.
   form.cmd.value="PDF_VIEW";
   form.reg_no.value = saveFileName;
   form.submit();
}

 

- JAVA controller

public void pdfView(WebForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   String href = "";
   String fileName = form.getReg_no();

   pdfServlet pdfServlet = new pdfServlet();
   pdfServlet.doGet(form, request, response);

}

pdfServlet 파일에 doGet 함수를 호출한다.

 

- pdfServlet

public class pdfServlet extends HttpServlet {
   public void doGet(WebForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
      String fileName = form.getReg_no();
      PrintWriter stream = null;
      BufferedInputStream buf = null;

      try {
         String pdfFilePath = PropertyUtil.getValue("pdf.file.path")+fileName+".pdf";  // application.properties에 선언된 pdf파일 경로 + saveFileName
         String pathChcek = PropertyUtil.getValue("pdf.file.path"); // application.properties에 선언된 pdf파일 경로

         File pdfFile = new File(pdfFilePath);

         if(!pdfFile.getCanonicalPath().replace(File.separator, "/").startsWith(pathChcek)) { // 호출된 파일 경로 확인(보안) *중요
            System.err.println("잘못된 접근입니다.");
            throw new ServletException("잘못된 접근입니다.");
         }

         stream = response.getWriter();

         response.setContentType("application/pdf"); // contentType 설정

         FileInputStream fis = new FileInputStream(pdfFile);
         response.setContentLength((int) pdfFile.length());
         buf = new BufferedInputStream(fis);
         int readBytes = 0;
         while ((readBytes = buf.read()) != -1) {
            stream.write(readBytes);
         }

      } catch (IOException ioe) {
         throw new ServletException(ioe.getMessage());
      } finally {
         if (stream != null) stream.close();
         if (buf != null) buf.close();
      }
   }

}

여기까지가 본인의 코드이다.

 

본인이 이번 기능에서 servlet을 사용하게된 이유는 

Java에서 파일 다운로드처럼 getOutputStream을 사용하여서 처리할 수 있는 거 같았는데

그렇게 기능을 만들어보니

" getoutputstream() has already been called for this response " 이라는 오류를 만나게 되었다.

물론 기능이 안되는 건 아니었다 pdf 파일을 볼 수 있었는데 저런 오류가 자꾸 나와서 검색 해본 결과

 

try {

out.clear(); //out--> jsp자체 객체

out=pageContext.pushBody(); //out--> jsp자체 객체

OutputStream out = response.getOutputStream(); 

}

이렇게 outputstream을 생성하기 전에 jsp자체의 out객체를 비워주고 사용해야 합니다.

 

위와 같은 답을 찾을 수 있었다.

 

하지만 물론 본인이 잘 사용하지 못해서 그렇겠지만 본인의 오류는 해결되지 않았다.

 

더 검색해본 결과

 

'jsp가 아닌 서블릿에서 처리해줘야한다'는 글을 봤다.

그래서 더 모르겠다...

 

그래도 일단 해보자

 

servlet 파일을 만들고 extends HttpServlet 을 해주고

public class pdfServlet extends HttpServlet

그렇게 오류가 생겼던 getOutputStream이 아닌

PrintWriter stream = null;
stream = response.getWriter();
while ((readBytes = buf.read()) != -1) {
   stream.write(readBytes);
}

PrintWriter를 사용했다.

 

생각 해보니 본인이 저번 파일 다운로드 글에서 처리했던 servlet 방식이랑 똑같다.

달라진 점이 있다면 

response.setContentType("application/pdf");

contentType을 pdf로 변경해주었다.

 

이렇게 servlet을 사용해 pdf를 읽어봤는데 이제 나를 괴롭혔던 

'getoutputstream() has already been called for this response' 이라는 오류 없이 pdf가 잘 읽힌다.

 

하지만 나는 아직도 servlet을 이해하지 못했고 찾아보니 본인 프로젝트는 Spring도 아니고 java 버전도 옛날 버전이라 사용하지 못했던 pdfViewer가 아주 많다.

 

왠만하면 그것들을 활용하길...

728x90
반응형