2016-02-17 3 views
1

Я обрабатываю некоторые большие pdf-файлы (до 100 МБ и около 2000 страниц) с помощью pdfbox. На некоторых страницах есть QR-код, я хочу разбить эти файлы на более мелкие, со страницами с одного QR-кода на другой. Я получил это, но размер файла результата совпадает с исходным файлом. Я имею в виду, если я вырезал pdf-файл размером 100 МБ в десять файлов, я получаю по десять файлов по 100 МБ каждый.Разделение большого файла Pdf с PDFBox получает большие файлы результатов

Это код:

PDDocument documentoPdf = 
     PDDocument.loadNonSeq(new File("myFile.pdf"), 
          new RandomAccessFile(new File("./tmp/temp"), "rw")); 

    int numPages = documentoPdf.getNumberOfPages(); 
    List pages = documentoPdf.getDocumentCatalog().getAllPages(); 

    int previusQR = 0; 
    for(int i =0; i<numPages; i++){ 
     PDPage page = (PDPage) pages.get(i); 
     BufferedImage firstPageImage =  
      page.convertToImage(BufferedImage.TYPE_USHORT_565_RGB , 200); 

     String qrText = readQRWithQRCodeMultiReader(firstPageImage, hintMap); 

     if(qrText != null and i!=0){ 
     PDDocument outputDocument = new PDDocument(); 
     for(int j = previusQR; j<i; j++){ 
      outputDocument.importPage((PDPage)pages.get(j)); 
      } 
     File f = new File("./splitting_files/"+previusQR+".pdf"); 
     outputDocument.save(f); 
     outputDocument.close(); 
     documentoPdf.close(); 
    } 

Я также попытался следующий код для сохранения нового файла:

PDDocument outputDocument = new PDDocument(); 

for(int j = previusQR; j<i; j++){ 
PDStream src = ((PDPage)pages.get(j)).getContents(); 
PDStream streamD = new PDStream(outputDocument); 
streamD.addCompression(); 

PDPage newPage = new PDPage(new 
      COSDictionary(((PDPage)pages.get(j)).getCOSDictionary())); 
newPage.setContents(streamD); 

byte[] buf = new byte[10240]; 
int amountRead = 0; 
InputStream is = null; 
OutputStream os = null; 
is = src.createInputStream(); 
os = streamD.createOutputStream(); 
while((amountRead = is.read(buf,0,10240)) > -1) { 
    os.write(buf, 0, amountRead); 
    } 

outputDocument.addPage(newPage); 
} 

File f = new File("./splitting_files/"+previusQR+".pdf"); 

outputDocument.save(f); 
outputDocument.close(); 

Но этот код создает файлы, которые отсутствуют некоторые содержания, а также имеют одинаковый размер чем оригинал.

Как создать файлы меньшего размера PDFs из более крупного? Возможно ли с помощью PDFBox? Есть ли другая библиотека, с помощью которой я могу преобразовать одну страницу в образ (для распознавания qr), а также разрешить разбить большой файл PDF на более мелкие?

Thx!

+1

Какая версия вы используете? Можете ли вы поделиться PDF? Эффект, который вы описываете, может произойти, если каждая страница ссылается на все ресурсы всех страниц, а не только на то, что она действительно использует. –

+0

Я использую версию 1.8.9 (я компилирую с Java 1.6). Вы можете скачать файл [здесь] (https://drive.google.com/open?id=0B0cAeEoswLtlMGZ2MWtJUVFaYUE "pdf") Я сгенерировал его с помощью [PDF_Chain ] (http://pdfchain.sourceforge.net/ "pdf_chain") – Nuria

+1

Текущая версия - 1.8.11 или 2.0 RC3. Я попробовал служебную программу PDFSplit с первым фрагментом, файл результатов (p 1- 59) равен 1,7 МБ. Сегодня я попробую ваш код, чтобы узнать, есть ли разница. –

ответ

1

Thx! Тилман, вы правы, команда PDFSplit генерирует файлы меньшего размера. Я проверил код PDFSplit и обнаружил, что он удаляет ссылки на страницы, чтобы избежать ненужных ресурсов.

Код извлекается из Splitter.class:

private void processAnnotations(PDPage imported) throws IOException 
    { 
     List<PDAnnotation> annotations = imported.getAnnotations(); 
     for (PDAnnotation annotation : annotations) 
     { 
      if (annotation instanceof PDAnnotationLink) 
      { 
       PDAnnotationLink link = (PDAnnotationLink)annotation; 
       PDDestination destination = link.getDestination(); 
       if (destination == null && link.getAction() != null) 
       { 
        PDAction action = link.getAction(); 
        if (action instanceof PDActionGoTo) 
        { 
         destination = ((PDActionGoTo)action).getDestination(); 
        } 
       } 
       if (destination instanceof PDPageDestination) 
       { 
        // TODO preserve links to pages within the splitted result 
        ((PDPageDestination) destination).setPage(null); 
       } 
      } 
      else 
      { 
       // TODO preserve links to pages within the splitted result 
       annotation.setPage(null); 
      } 
     } 
    } 

Так в конце концов мой код выглядит следующим образом:

PDDocument documentoPdf = 
     PDDocument.loadNonSeq(new File("docs_compuestos/50.pdf"), new RandomAccessFile(new File("./tmp/t"), "rw")); 

     int numPages = documentoPdf.getNumberOfPages(); 
     List pages = documentoPdf.getDocumentCatalog().getAllPages(); 


     int previusQR = 0; 
     for(int i =0; i<numPages; i++){ 
      PDPage firstPage = (PDPage) pages.get(i); 
      String qrText =""; 


      BufferedImage firstPageImage = firstPage.convertToImage(BufferedImage.TYPE_USHORT_565_RGB , 200); 


      firstPage =null; 

      try { 
       qrText = readQRWithQRCodeMultiReader(firstPageImage, hintMap); 
      } catch (NotFoundException e) { 
       e.printStackTrace(); 
      } finally { 
       firstPageImage = null; 
      } 


     if(i != 0 && qrText!=null){ 
        PDDocument outputDocument = new PDDocument(); 
        outputDocument.setDocumentInformation(documentoPdf.getDocumentInformation()); 
        outputDocument.getDocumentCatalog().setViewerPreferences(
          documentoPdf.getDocumentCatalog().getViewerPreferences()); 


        for(int j = previusQR; j<i; j++){ 
         PDPage importedPage = outputDocument.importPage((PDPage)pages.get(j)); 

         importedPage.setCropBox(((PDPage)pages.get(j)).findCropBox()); 
         importedPage.setMediaBox(((PDPage)pages.get(j)).findMediaBox()); 
         // only the resources of the page will be copied 
         importedPage.setResources(((PDPage)pages.get(j)).getResources()); 
         importedPage.setRotation(((PDPage)pages.get(j)).findRotation()); 

         processAnnotations(importedPage); 


        } 


        File f = new File("./splitting_files/"+previusQR+".pdf"); 

        previusQR = i; 

        outputDocument.save(f); 
        outputDocument.close(); 
       } 
      } 


     } 

Большое спасибо !!

+0

Ничего себе, ты хороший. (Я только узнал об этом, но вы избили меня). Я подумаю о хорошем дополнительном комментарии для javadoc importPage. –

+1

Обратите внимание на два TODO. Вы можете вызвать processAnnotations() для каждой страницы после того, как создали новый документ со всеми страницами, а затем проверьте, чтобы страница была «нулевой» в вашем целевом документе или нет. –

+0

Пожалуйста, нажмите зеленую галочку (если имеется). Вы не получите никаких баллов за это, но вопрос появится как ответ. Измените также заголовок на свой вопрос во что-то вроде «... все равно получите большие файлы результатов» или какой-либо другой текст с тем же значением, чтобы найти больше «жертв» этой проблемы. Я уже изменил javadoc 2.0 и сделаю это для 1.8 позже. –

Смежные вопросы