Overview

PDF파일을 읽어서 String을 추출해야할 일이 생겼다. Embedding도 그렇지만 PDF 파일을 읽어서 서버로 보내야되는? 일이 생긴것이다. PDF파일에 대한 상태, 위치에 대한 방법이 갈리며 그 이후 파일을 읽어서 추출한다.

Contents

  • 사용방법
implementation 'org.apache.pdfbox:pdfbox'
//or
implementation 'org.apache.pdfbox:pdfbox:2.0.27'

BuildTool gradle 사용하여 가져온다.

또는 https://mvnrepository.com에서 원하는 Jar를 검색하여 bundle File을 다운받아 jar를 Build Path에 지정해준다.

너무 legacy 또는 기본,, 옛날등의 방식이지만,,,

  • String 추출
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;

    private String extractTextFromPDF(File pdfFile) throws IOException {
        try (PDDocument document = PDDocument.load(pdfFile)) {
            PDFTextStripper stripper = new PDFTextStripper();
            return stripper.getText(document);
        }
    }

File 타입의 파라미터로 넘겨주어 String을 추출한다. 또는 byte[],,

  • PDF의 위치 PDF파일이 로컬에 또는 서버에 있을 수 있다.
    1. Resource
         @Value("classpath:/doc/w1-2_02_docker_network.pdf")
         private Resource pdf;
         ...
         pdf.getFile()
      

      Resource내에 디렉토리를 두어 해당 파일을 읽는다.\n 물론 resource buildPath설정되있겟지.

    2. File
         File file = new File("절대경로");
      

      절대경로로 파일을 읽어서 인자로 던진다.

    3. URL
             String urlString = "https://docs.spring.io/spring-boot/docs/3.2.7/reference/pdf/spring-boot-reference.pdf";
             URL url = new URL(urlString);
             // #1 window
             // c:\Users\09930255\AppData\Local\Temp 이하 경로에 해당 파일명, 확장자로 임시파일이 생성된다.
             Path tempFile = Files.createTempFile("spring-boot-reference", ".pdf");
      
             try (InputStream in = url.openStream()) {
                 Files.copy(in, tempFile, StandardCopyOption.REPLACE_EXISTING);
             }
      
             ...
             tempFile.toFile()
      

      Files.createTempFile을 이용해 껍데기를 만들고 FileCopy로 복사하여 toFile()로 인자를 전달한다.
      파일 시스템에 저장되므로 메모리 사용이 적기 때문에 큰파일을 처리하기에 적합하다.

      또는

         String urlString = "https://docs.spring.io/spring-boot/docs/3.2.7/reference/pdf/spring-boot-reference.pdf";
         try(InputStream in = new URL(urlString).openStream();
             ByteArrayOutputStream buffer = new ByteArrayOutputStream()){
             byte[] data = new byte[1024];
             int nRead;
             while((nRead = in.read(data, 0, data.length)) != -1){
                 buffer.write(data, 0, nRead);
             }    
      
             try (PDDocument document = PDDocument.load(buffer.toByteArray())) {
             PDFTextStripper stripper = new PDFTextStripper();
             stripper.getText(document); // 
             }
         }
      

      byte[]로 전달하여 toByteArray()로 인자를 넘기면된다.
      메모리에서 직접 처리하므로 속도에 장점이 있으나 큰파일을 처리하기엔 적합하지 않다.

마치며

PDF 파일내 String을 추출하는 기능을 만들어보았다. 한가지 중요한점,, PDF파일내 텍스트가 긇어져야 읽어지는거 같다. Scan된 파일은 안되는듯,,, 뭐 지금도 문서보안 MarkAny쪽 암호화 걸린 파일을 읽다보니 Header doesn’t contain versioninfo 에러 메시지가 나오며, 디버그 해보니 Docuemnt 암호화가 바이너리 자체에 걸려있음을 확인하여 좌절하였다. 또 이 암호화된 문서를 풀려면 서버간 통신 및 정책,, 등등이 필요하겟찌…