Java使用PDFBox操作PDF文件

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/qq_37022150/article/details/79486730

前言:

前段时间在完成公司安排的任务同时,利用空余时间做了一个使用java操作pdf的功能
刚开始没什么头绪,直到在网上找到了pdfBox,
pdfBox是apach提供的免费,开源的pdf操作工具,使用起来也挺方便,github可下载
我也上传了一份, [ pdfbox-1.8.9.zip ]

1首先,导入jar

我是maven方式导入
PS:
这个jar里面囊括了所有的pdfbox操作工具类,导入这一个就够了
(我在找工具类的时候,看到别的博主导了pdfbox的很多类,然后一股脑也导了进去,结果jar包冲突,原来只导入一个,那就是官方已经整合好的那个,就够了)

        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox-app</artifactId>
            <version>1.8.10</version>
        </dependency>
  
  

    2.在你的项目中创建一个工具类

    2.1这个类的取名:随意,
    我是取的pdfUtil

    2.2当然,如果你想将操作记录入录到数据库的话,你也可以创建一个pdf的实体类
    这个实体类创不创建大家随意,我贴一下我的实体类的属性,供参考

        //实体类的名称:pdfDomainVO
    
        private Integer id;//id
    
        private Date time;//操作时间
    
        private String filename;//文件名
    
        private String filesize;//文件大小
    
        private String filetype;//文件类型
    
        private String details;//操作详情
    
        private String content;//pdf中内容
    
        private String outputfile;//输出路径(保存路径)
    
        private String inputfile;//要操作的pdf路径
    
        private String strtofind;//需要替换的文本
    
        private String message;//替换的文本
    
        private String imagefile;//图片路径
    
        private String imagelist;//图片集合
    
        private Integer pageno;//指定页码
    
        private Integer pages;//总页数
    
        private Integer rid;//...
    
        private Integer pageoperation;//操作页数
    
        private Integer pagestart;//开始页
    
        private Integer pageend;//结束页
    
        private String position;//位置:X,Y
    
        private String fileSizeAfter;//操作后文件大小
    
        private Integer status;//状态
    
        private Integer afterPages;//操作后页码
    
        private Integer imgSize;//图片大小
      
      

      3.在pdfUtil写代码

      PS:我下面会有用到pdfDomainVO实体类的时候,大家参考下上面贴的属性

      大家可以在pdfbox-1.8.9.zip文件夹中,找到examples文件夹
      里面有很多事例,比如:
      1创建一个pdf文件
      2读取pdf中,全部文字信息(可用String接收)
      3替换pdf中字符(中文我还没有解决好,不好意思啊)
      4在pdf中插入图片
      等等操作……
      PS:我现在贴一下我的代码

      —–1创建1到多个空白页面

      /***
           * 创建1到多个空白页面
           * @param file
           * @throws IOException
           * @throws COSVisitorException
           */
          public static void createBlank( String outputFile ) throws IOException, COSVisitorException
          {
              //首先创建pdf文档类
              PDDocument document = null;
              try
              {
                  document = new PDDocument();
                  //实例化pdf页对象
                  PDPage blankPage = new PDPage();
                  PDPage blankPage1 = new PDPage();
                  PDPage blankPage2 = new PDPage();
                  //插入文档类
                  document.addPage( blankPage );
                  document.addPage( blankPage1 );
                  document.addPage( blankPage2 );
                  //记得一定要写保存路径,如"H:\\text.pdf"
                  document.save( outputFile );
                  System.out.println("over");
              }
              finally
              {
                  if( document != null )
                  {
                      document.close();
                  }
              }
          }
        
        

        —–2读取pdf中文字信息(全部)

            /**
             * 读取pdf中文字信息(全部)
             */
            public static void READPDF(String inputFile){
                //创建文档对象
                PDDocument doc =null;
                String content="";
                try {
                    //加载一个pdf对象
                    doc =PDDocument.load(new File(inputFile));
                    //获取一个PDFTextStripper文本剥离对象  
                    PDFTextStripper textStripper =new PDFTextStripper("GBK");
                    content=textStripper.getText(doc);
                    vo.setContent(content);
                    System.out.println("内容:"+content);
                    System.out.println("全部页数"+doc.getNumberOfPages());  
                    //关闭文档
                    doc.close();
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
          
          

          —–3读取pdf中文字信息(指定页面)

              /**
               * 读取pdf中文字信息(指定从第几页开始)
               */
              public static pdfDomainVO readPageNO(pdfDomainVO vo){   
                  String content="";        
                  try{
                      PDDocument document = PDDocument.load(vo.getInputfile());
                      // 获取页码
                      int pages = document.getNumberOfPages();
                       // 读文本内容
                       PDFTextStripper stripper=new PDFTextStripper();
                       // 设置按顺序输出
                       stripper.setSortByPosition(true);
                       stripper.setStartPage(vo.getPageno());
                       stripper.setEndPage(vo.getPageno());
                       //获取内容
                       content = stripper.getText(document);
                       vo.setContent(content);
                       System.out.println("function : readPageNO over");
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return vo;
              }
          
            
            

            —–4替换指定pdf文件的文字内容(这个比较复杂,当时看api看了好久,然后一个一个的吧注释添了上去)

            /**
                 * 替换指定pdf文件的文字内容
                 * @param args
                 */
                public static pdfDomainVO replaceContent(pdfDomainVO vo)
                throws IOException,COSVisitorException{
                    //创建一个文档对象
                    PDDocument doc =null;
                    try {
                        //加载文件
                        doc =PDDocument.load(vo.getInputfile());
                        //获取全部页数
                        List pages= doc.getDocumentCatalog().getAllPages();
                        //获取与i对应的页面
                        PDPage page = (PDPage)pages.get( vo.getPageno() );
                        //流对象来接收当前page的内容
                        PDStream contents = page.getContents();
                        //PDF流对象剖析器(这将解析一个PDF字节流并提取操作数,等等)
                        PDFStreamParser parser =new PDFStreamParser(contents.getStream());
                        //这将分析流中的标记
                        parser.parse();
                        //用list存流中的所有标记
                        List tokens =parser.getTokens();
                        for (int j = 0; j < tokens.size(); j++) {
                            //创建一个object对象去接收标记
                            Object next = tokens.get( j );
                            //instanceof判断其左边对象是否为其右边类的实例
                            if(next  instanceof PDFOperator ) {
                                //pdf操作器对象
                                PDFOperator op =(PDFOperator)next;
                                //TJ和TJ是显示的两个操作符。 
                                //PDF中的字符串 
                                if(op.getOperation().equals("Tj")){
                                    //COSString对象>>创建java字符串的一个新的文本字符串。
                                    COSString previous = (COSString)tokens.get( j-1 );
                                    //将此字符串的内容作为PDF文本字符串返回。 
                                    String string=previous.getString();
                                    //replaceFirst>>替换第一个字符
                                    string = string.replaceFirst( vo.getStrtofind(), vo.getMessage() );
                                    System.out.println(string);                           
                                    System.out.println(string.getBytes("GBK"));
                                    //重置COSString对象
                                    previous.reset();
                                    //设置字符编码格式
                                    previous.append(string.getBytes("GBK") );
                                }else if(op.getOperation().equals("TJ")){
                                    //COSArray是pdfbase对象数组,作为PDF文档的一部分
                                    COSArray previous  =(COSArray)tokens.get( j-1 );
                                    //循环previous
                                    for (int k = 0; k < previous.size(); k++) {
                                        //这将从数组中获取一个对象,这将取消引用该对象
                                        //如果对象为cosnull,则返回null
                                        Object arrElement = previous.getObject( k );
                                        if( arrElement instanceof COSString ){
                                            //COSString对象>>创建java字符串的一个新的文本字符串。
                                            COSString cosString =(COSString)arrElement;
                                            //将此字符串的内容作为PDF文本字符串返回。 
                                            String string =cosString.getString();
                                            //替换
                                            string = string.replaceFirst(  vo.getStrtofind(), vo.getMessage());
                                            //重置COSString对象
                                            cosString.reset();
                                            //设置字符编码格式
                                            cosString.append(string.getBytes("GBK") );
                                        }
                                    }
                                }
                            }
                        }
                         //创建一个PDStream 流对象
                         PDStream updatedStream = new PDStream(doc);
                         //创建一个输出流接收updatedStream
                         OutputStream out =updatedStream.createOutputStream();
                         //将接受一个列表并写出它们的流。 
                         ContentStreamWriter tokenWriter  =new ContentStreamWriter(out);
                         //写入一系列标记,后面跟着一行新行
                         tokenWriter.writeTokens(tokens);
                         //当前页设置新的内容
                         page.setContents( updatedStream );
                        //修改后保存的路径
                        doc.save(vo.getOutputfile());
                        //操作后的页数
                        vo.setAfterPages(doc.getNumberOfPages());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }finally{
                        if( doc != null ){
                            //关闭文档
                            doc.close();
                        }
                    }
                    return vo;
                }
              
              

              —–5在pdf中插入图片(按指定页数插入)

              /**
                   * 在pdf中插入图片
                   * @param inputFile
                   * @param image
                   * @param outputFile
                   * @throws IOException
                   * @throws COSVisitorException
                   */
                  public static pdfDomainVO  insertImage( pdfDomainVO vo ) 
                            throws IOException, COSVisitorException{
                      //偏移量设置
                      String[] position =vo.getPosition().split(",");
                      int x =Integer.valueOf(position[0]);
                      int y =Integer.valueOf(position[position.length-1]);
                      //创建一个文档对象
                      PDDocument doc =null;
                      try {
                          //加载
                          doc = PDDocument.load(vo.getInputfile());
                          //获取加载进来的pdf文件的页面
                          PDPage page = (PDPage)doc.getDocumentCatalog().getAllPages().get( vo.getPageno() );
                          //pdfbox中图片对象类
                          PDXObjectImage ximage = null;
                          //判断是否是.jpg格式的图片
                          if( vo.getImagefile().toLowerCase().endsWith( ".jpg" ) ){
                              //传入一张图片
                               ximage = new PDJpeg(doc, new FileInputStream( vo.getImagefile() ) ); 
                          }//如果是tif或tiff格式
                          else if (vo.getImagefile().toLowerCase().endsWith(".tif") || vo.getImagefile().toLowerCase().endsWith(".tiff")){
                               ximage = new PDCcitt(doc, new RandomAccessFile(new File(vo.getImagefile()),"r"));
                          }else{
                              //Image和BufferedImage的主要作用就是将一副图片加载到内存中
                              BufferedImage awtImage = ImageIO.read( new File( vo.getImagefile() ) );
                              ximage = new PDPixelMap(doc, awtImage);
                          }
                          //这是选择如何处理流:覆盖、追加
                          PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true);
                          //控制图片的大小
                          float scale = vo.getImgSize();
                          scale = scale/10;//(这个值最好是0.1~1,0.5就已经很大了)
              
                          //ximage.setHeight(ximage.getHeight()/5);
                          //ximage.setWidth(ximage.getWidth()/5);
                           System.out.println(ximage.getHeight());
                           System.out.println(ximage.getWidth());
                           //设置位移等参数
                           contentStream.drawXObject(ximage, x, y, ximage.getWidth()*scale, ximage.getHeight()*scale);
                           //关闭流对象
                           contentStream.close();
                           //保存路径
                           doc.save( vo.getOutputfile() );
                           //操作后的页数
                           vo.setAfterPages(doc.getNumberOfPages());
                      } catch (Exception e) {
                          e.printStackTrace();
                      }finally{
                          if( doc != null ){
                              //关闭文档
                              doc.close();
                          }
                      }   
                      return vo;
                   }
                
                

                —–6指定页数的PDF文件转换为图片

                /***
                     * 指定页数的PDF文件转换为图片:
                     * @param inputFile
                     * @param outputFile 这里指定文件夹
                     */
                    public static pdfDomainVO toImage( pdfDomainVO vo ) {
                        try {
                            //加载
                            PDDocument doc = PDDocument.load(vo.getInputfile());
                            //
                            //int pageCount = doc.getPageCount();
                            ////获取全部页数
                            //指定单页转pdf
                            List pages = doc.getDocumentCatalog().getAllPages();
                            if(vo.getPageno()!=null){
                                String count=(int)(Math.random()*1000)+"-"+(int)(Math.random()*1000);
                                //接收页面
                                PDPage page = (PDPage) pages.get(vo.getPageno());
                                //定义图片操作对象来设置图片
                                BufferedImage image = page.convertToImage();
                                //定义迭代器对象存储
                                Iterator iter = ImageIO.getImageWritersBySuffix("jpg");
                                //图片写入器对象写入图片
                                ImageWriter writer = (ImageWriter) iter.next();
                                //循环保存图片
                                File outFile = new File(vo.getOutputfile()+vo.getFilename()+"-"+(vo.getPageno()+1)+".jpg");
                                //创建文件输出流对象
                                FileOutputStream out = new FileOutputStream(outFile);
                                //ImageIO去实现ImageOutputStream获取当前图片
                                ImageOutputStream outImage = ImageIO.createImageOutputStream(out);
                                writer.setOutput(outImage);
                                writer.write(new IIOImage(image, null, null));
                            }else{
                                //循环
                                for (int i = 0; i < pages.size(); i++) {
                                    //接收页面
                                    PDPage page = (PDPage) pages.get(i);
                                    //定义图片操作对象来设置图片
                                    BufferedImage image = page.convertToImage();
                                    //定义迭代器对象存储
                                    Iterator iter = ImageIO.getImageWritersBySuffix("jpg");
                                    //图片写入器对象写入图片
                                    ImageWriter writer = (ImageWriter) iter.next();
                                    //循环保存图片
                                    File outFile = new File(vo.getOutputfile()+i+".jpg");
                                    //创建文件输出流对象
                                    FileOutputStream out = new FileOutputStream(outFile);
                                    //ImageIO去实现ImageOutputStream获取当前图片
                                    ImageOutputStream outImage = ImageIO.createImageOutputStream(out);
                                    writer.setOutput(outImage);
                                    writer.write(new IIOImage(image, null, null));
                                }
                            }
                            //关文档
                            doc.close();
                            //操作后的页数
                            vo.setAfterPages(doc.getNumberOfPages());
                            System.out.println("over");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return vo;
                    }
                  
                  

                  —–7指定页插入一段文字(大家可自调字体,插入文字的位置)

                  /***
                       * 指定页插入一段文字
                       * @param inputFile
                       * @param message
                       * @param outputFile
                       * @throws IOException
                       * @throws COSVisitorException
                       */
                      public static pdfDomainVO InsertPageContent (pdfDomainVO vo ) throws IOException, COSVisitorException
                      { 
                          // the document
                          PDDocument doc = null;
                          try
                          {
                              doc = PDDocument.load( vo.getInputfile() );
                              List allPages = doc.getDocumentCatalog().getAllPages();
                              PDFont font = PDType1Font.HELVETICA_BOLD;
                              //字体大小
                              float fontSize = 36.0f;
                              PDPage page = (PDPage)allPages.get( vo.getPageno() );
                              PDRectangle pageSize = page.findMediaBox();
                              float stringWidth = font.getStringWidth( vo.getMessage() )*fontSize/1000f;
                              // calculate to center of the page
                              int rotation = page.findRotation(); 
                              boolean rotate = rotation == 90 || rotation == 270;
                              float pageWidth = rotate ? pageSize.getHeight() : pageSize.getWidth();
                              float pageHeight = rotate ? pageSize.getWidth() : pageSize.getHeight();
                              double centeredXPosition = rotate ? pageHeight/2f : (pageWidth - stringWidth)/2f;
                              double centeredYPosition = rotate ? (pageWidth - stringWidth)/2f : pageHeight/2f;
                              // append the content to the existing stream
                              PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true,true);
                              contentStream.beginText();
                              // set font and font size
                              contentStream.setFont( font, fontSize );
                              // set text color to red
                              contentStream.setNonStrokingColor(255, 0, 0);
                              if (rotate)
                              {
                                  // rotate the text according to the page rotation
                                  contentStream.setTextRotation(Math.PI/2, centeredXPosition, centeredYPosition);
                              }
                              else
                              {
                                  contentStream.setTextTranslation(centeredXPosition, centeredYPosition);
                              }
                              contentStream.drawString( vo.getMessage() );
                              contentStream.endText();
                              contentStream.close();
                              vo.setAfterPages(doc.getNumberOfPages());
                              doc.save( vo.getOutputfile() );
                              System.out.println("over");
                          }
                          finally
                          {
                              if( doc != null )
                              {
                                  doc.close();
                              }
                          }
                          return vo;
                      }
                    
                    

                    —–8提取图片并保存

                    /**
                         * 提取图片并保存
                         * @param pdfDomainVO 
                         * @throws IOException 
                         * 
                         */
                        public static pdfDomainVO extractImage(pdfDomainVO vo ) throws IOException{
                            //创建文档  
                            PDDocument doc=null;
                            try{
                                //加载 pdf 文档,获取PDDocument文档对象
                                doc=PDDocument.load(vo.getInputfile());           
                                /** 文档页面信息 **/  
                                //获取PDDocumentCatalog文档目录对象
                                PDDocumentCatalog catalog = doc.getDocumentCatalog();
                                //获取文档页面PDPage列表
                                List pages = catalog.getAllPages();  
                                int pageNum=pages.size();   //文档页数
                                PDPage page = null;
                                if(vo.getPageno()!=null){
                                     page = ( PDPage ) pages.get( vo.getPageno() ); 
                                     if( null != page ){  
                                         PDResources resource = page.findResources();                      
                                         //获取页面图片信息 
                                         Map<String,PDXObjectImage> imgs = resource.getImages();                    
                                         for(Map.Entry<String,PDXObjectImage> me: imgs.entrySet()){
                                             //System.out.println(me.getKey());
                                             PDXObjectImage img = me.getValue();  
                                             //保存图片,会自动添加图片后缀类型
                                             img.write2file( vo.getOutputfile() + vo.getFilename()+"-"+(vo.getPageno()+1) );     
                                         }  
                                     }  
                                }else{
                                    //遍历每一页
                                    for( int i = 0; i < pageNum; i++ ){  
                                        //取得第i页
                                         page = ( PDPage ) pages.get( i ); 
                                        if( null != page ){  
                                            PDResources resource = page.findResources();                      
                                            //获取页面图片信息 
                                            Map<String,PDXObjectImage> imgs = resource.getImages();                    
                                            for(Map.Entry<String,PDXObjectImage> me: imgs.entrySet()){
                                                String count=(int)(Math.random()*1000)+"-"+(int)(Math.random()*1000);
                                                //System.out.println(me.getKey());
                                                PDXObjectImage img = me.getValue();  
                                                //保存图片,会自动添加图片后缀类型
                                                img.write2file( vo.getOutputfile() + count );  
                                            }  
                                        }  
                                    } 
                                }
                                //操作后的页数
                                vo.setAfterPages(doc.getNumberOfPages());
                                System.out.println("extractImage:over");
                            }  finally
                            {
                                if( doc != null )
                                {
                                    doc.close();
                                }
                            }
                            return vo;
                        }
                      
                      
                      /ul>

                    —–9PDF文档中删除页面(不能删除最后一页!)

                        /***
                         * PDF文档中删除页面
                         * 一个PDF文档必须至少有一页,且不能删除最后一页!
                         * @param inputFile
                         * @param outputFile
                         * @throws Exception
                         */
                        public static pdfDomainVO removePage(pdfDomainVO vo) throws Exception
                        {
                            vo.setStatus(Details.FailStatus);
                            PDDocument document = null;
                            try
                            {
                                document = PDDocument.load(vo.getInputfile() );
                                if( document.isEncrypted() )
                                {
                                    throw new IOException( "Encrypted documents are not supported for this example" );
                                }
                                if( document.getNumberOfPages() <= 1 )
                                {
                                    throw new IOException( "Error: A PDF document must have at least one page, " +
                                                           "cannot remove the last page!");
                                }
                                document.removePage( vo.getPageno() );
                                document.save(vo.getOutputfile() );
                                //操作后的页数
                                vo.setAfterPages(document.getNumberOfPages());
                                //设置成功状态
                                vo.setStatus(Details.SuccessStatus);
                                System.out.println("over");
                            }
                            finally
                            {
                                if( document != null )
                                {
                                    document.close();
                                }
                            }
                            return vo;
                        }
                      
                      

                      pdfbox很强大,最主要是开源,(就是TMD不支持中文)以上只是部分功能,大家如果还想拓展,可以参考官方的事例和api

                      PS:遗憾的是,我没有处理好,替换文字或者是插入文字时,中文乱码问题,有处理好的同学记得和博主说一下,大家共同进步

                      这有一篇文:http://blog.csdn.net/undergrowth/article/details/39136673是对于pdfbox各个方法,属性解析的比较好的文,大家可以去看下


                      猜你喜欢

                      转载自blog.csdn.net/qq_37022150/article/details/79486730