1. 程式人生 > >使用fileinput+pdfbox獲取pdf文件指定區域的內容

使用fileinput+pdfbox獲取pdf文件指定區域的內容

本功能實現的思路如下:
1. 通過bootstrap-fileinput外掛實現上傳pdf文件
2. 通過pdfbox將pdf文件轉換成圖片格式,並儲存在專案的根目錄上。
3.訪問根目錄上的由pdf文件轉成的圖片,使用jquery-ui選取指定區域。
4.將指定區域的座標x,y,width,heigth等資訊傳遞到後臺,按比例獲取pdf文件上的指定區域的內容。
5.通過pdfbox解析指定區域的內容,並返回到前臺進行展示。

1)fileinput+pdfbox的使用

一、下載安裝

原始碼在github上共享,fileinout下載地址直接clone下來就可以了。
在html頁面引入css資料夾的fileinput.min.css


引入js資料夾中的fileinput.min.js
引入locale資料夾下的zh.js

二、html頁面

<div class="container">



        <form id="myForm">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title" id="myModalLabel">請選擇PDF檔案</h4>
                </div
> <div class="modal-body"> <input type="file" name="txt_file" id="txt_file" class="file-loading" /> </div> </div> </form> </div> <div id="picture" style="display: none"
> <button class="btn btn-default" onclick="getposition()">測量</button> <div id="box"> <img src="" id="img1"> <img src="" id="img2"> <div id="main"> <div id="left-up" class="minDiv left-up"></div> <div id="up" class="minDiv up"></div> <div id="right-up" class="minDiv right-up"></div> <div id="right" class="minDiv right"></div> <div id="right-down" class="minDiv right-down"></div> <div id="down" class="minDiv down"></div> <div id="left-down" class="minDiv left-down"></div> <div id="left" class="minDiv left"></div> </div> </div> <div id="preview"> <img src="" id="img3"> </div> </div>

其中input標籤是重點,multiple表示允許同時上傳多個檔案,class=“file-loading”表示標籤的樣式。這裡很重要,如果class="file",則中文化不能生效。

這裡寫圖片描述

三、js程式碼

$(function() {
        //0.初始化fileinput
        var oFileInput = new FileInput();
        oFileInput.Init("txt_file", "/api/OrderApi/ImportOrder");

    });
    var FileInput = function() {
        var oFile = new Object();

        //初始化fileinput控制元件(第一次初始化)
        oFile.Init = function(ctrlName, uploadUrl) {
            var control = $('#' + ctrlName);

            //初始化上傳控制元件的樣式
            control.fileinput({
                language : 'zh', //設定語言
                uploadUrl : 'uploadpdf', //上傳的地址
                allowedFileExtensions : [ 'pdf', 'jpg', 'gif', 'png' ],//接收的檔案字尾
                showUpload : true, //是否顯示上傳按鈕
                showCaption : false,//是否顯示標題
                browseClass : "btn btn-primary", //按鈕樣式     
                //dropZoneEnabled: false,//是否顯示拖拽區域
                //minImageWidth: 50, //圖片的最小寬度
                //minImageHeight: 50,//圖片的最小高度
                //maxImageWidth: 1000,//圖片的最大寬度
                //maxImageHeight: 1000,//圖片的最大高度
                //maxFileSize: 0,//單位為kb,如果為0表示不限制檔案大小
                //minFileCount: 0,
                maxFileCount : 10, //表示允許同時上傳的最大檔案個數
                enctype : 'multipart/form-data',
                validateInitialCount : true,
                previewFileIcon : "<i class='glyphicon glyphicon-king'></i>",
                msgFilesTooMany : "選擇上傳的檔案數量({n}) 超過允許的最大數值{m}!",
            });

            //上傳成功需要處理的內容。
            $("#txt_file").on("fileuploaded",
                    function(event, data, previewId, index) {
                        imgname=data.response.imgname;
                        filename=data.response.filename;
                        pdfheight=data.response.pdfheight;
                        pdfwidth=data.response.pdfwidth;
                        $("#box").height(pdfheight); //設定box的div的高度
                        $("#myForm").hide(500); //上傳的表單隱藏
                        $("#picture").show(); //顯示圖片的div顯示
                        $("#img1,#img2,#img3").attr("src",path+"/static/img/pdf/"+imgname); //將幾個截
                                                            //取圖片用到的圖片標籤的src路徑指向後臺傳遞過來的圖片名
                    });
        }
        return oFile;
    };
    function getposition(){
        var imgwidth=$('#img1').width();
        var imgheight=$('#img1').height(); //獲取圖片的大小
        var x = $('#main').position().left*pdfwidth/imgwidth; 
        var y = $('#main').position().top*pdfheight/imgheight; 
        var width=$('#main').width()*pdfwidth/imgwidth;
        var height=$('#main').height()*pdfheight/imgheight;  //獲取選區框的位置和寬度高度並按pdf文件的大小和圖片的大小進行縮放
        console.log('x:'+x+'_y:'+y+'_width:'+width+'_height:'+height);
        var data={
                'x':x,
                'y':y,
                'width':width,
                'height':height,
                'filename':filename,
                'imgname':imgname
                };
        var jsonstring=JSON.stringify(data); //將各個引數的json物件轉換成json字串
        console.log(jsonstring);
        post('getpdftext', {"jsonstring" :jsonstring}); //呼叫post方法傳遞這些引數到後臺
    }
function post(URL, PARAMS) {        
    var temp = document.createElement("form");        
    temp.action = URL;        
    temp.method = "post";        
    temp.style.display = "none";  
    temp.setAttribute('target', '_blank');
    for (var x in PARAMS) {        
        var opt = document.createElement("textarea");        
        opt.name = x;        
        opt.value = PARAMS[x];        
        // alert(opt.name)        
        temp.appendChild(opt);        
    }        
    document.body.appendChild(temp);        
    temp.submit();        
    return temp;        
}

說明:
* fileinput()方法裡面傳入的是一個json資料,它裡面有很多屬性,每個屬性代表著初始化上傳控制元件的時候的特性,如果這些屬性都不設定,則表示使用預設的設定。如果園友們想看看它裡面有哪些屬性,可以開啟fileinput.js的原始碼,在它的最後如圖:

![](https://images2015.cnblogs.com/blog/459756/201511/459756-20151130164419483-421618128.png)

這些屬性如果不特意設定,就會使用預設值。
  • $("#txt_file").on("fileuploaded", function (event, data, previewId, index) {}這個方法註冊上傳完成後的回撥事件。也就是後天處理上傳的檔案之後進入這個方法裡面處理。

    這裡寫圖片描述

四、接收pdf上傳的後臺程式碼

@ResponseBody
    @RequestMapping("uploadpdf")
    public JSONObject pdfupload(@RequestParam MultipartFile[] txt_file,HttpServletRequest request) throws IOException{
        //如果只是上傳一個檔案,則只需要MultipartFile型別接收檔案即可,而且無需顯式指定@RequestParam註解   
        //如果想上傳多個檔案,那麼這裡就要用MultipartFile[]型別來接收檔案,並且還要指定@RequestParam註解   
        //並且上傳多個檔案時,前臺表單中的所有<input type="file"/>的name都應該是myfiles,否則引數裡的myfiles無法獲取到所有上傳的檔案   
        request.setCharacterEncoding("UTF-8");

        //如果用的是Tomcat伺服器,則檔案會上傳到  {服務釋出位置}\\WEB-INF\\upload\\資料夾中   
        String realPath = request.getSession().getServletContext().getRealPath("/WEB-INF/upload");
        String imgDir = request.getSession().getServletContext().getRealPath("/static/img/pdf");
        //這裡不必處理IO流關閉的問題,因為FileUtils.copyInputStreamToFile()方法內部會自動把用到的IO流關掉,我是看它的原始碼才知道的   
        //FileUtils.copyInputStreamToFile(myfile.getInputStream(), new File(realPath, myfile.getOriginalFilename()));   
        String fileBname="";

        for (MultipartFile mFile : txt_file) {  
            String originalFileName= mFile.getOriginalFilename();//獲取檔名稱  
            String UUID = java.util.UUID.randomUUID().toString();  
            byte[] bytes = mFile.getBytes();//獲取位元組陣列  
            fileBname = UUID+"."+mFile.getOriginalFilename().substring(mFile.getOriginalFilename().lastIndexOf(".")+1);
            File folder = new File(realPath);
            //資料夾路徑不存在
            if (!folder.exists() && !folder.isDirectory()) {
                System.out.println("資料夾路徑不存在,建立路徑:" + realPath);
                folder.mkdirs();
            } else {
                System.out.println("資料夾路徑存在:" + realPath);
            }

            // 如果檔案不存在就建立
            File file = new File(realPath +File.separator+ fileBname);
            if (!file.exists()) {
                System.out.println("檔案不存在,建立檔案:" );
                FileOutputStream fos= new FileOutputStream(file); //寫出到檔案  
                fos.write(bytes);  
                fos.flush();  
                fos.close();
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("檔案已存在,檔案為:" + realPath + fileBname);
            }
        }  

        PdfUtil pdfUtil=new PdfUtil(realPath +File.separator+ fileBname);//獲取pdf工具類物件,這個工具類是我自己寫的

        String imgname=pdfUtil.getimgFrompdf(imgDir);//呼叫此工具類將指定目錄的pdf轉成圖片,並趕回圖片的name 
        float pdfwidth=pdfUtil.getpageWidth(0); //獲取頁面的寬度 用於後面與前面圖片大小做比例縮放。
        float pdfheight=pdfUtil.getpageHeight(0); //獲取頁面的高度

        /*ModelAndView mv=new ModelAndView("/product/uploadsuccess");*/
        JSONObject json=new JSONObject();
        json.put("filename", fileBname);
        json.put("imgname", imgname);
        json.put("pdfwidth", pdfwidth);
        json.put("pdfheight", pdfheight);

        return json;
    }

其中MultipartFile是spring框架中提供的多檔案上傳工具,需要引入jar包:

<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

不同情況下屬性的使用也不相同:
* 如果只是上傳一個檔案,則只需要MultipartFile型別接收檔案即可,而且無需顯式指定@RequestParam註解.
* 如果想上傳多個檔案,那麼這裡就要用MultipartFile[]型別來接收檔案,並且還要指定@RequestParam註解
* 並且上傳多個檔案時,前臺表單中的所有<input type="file"/>的name都應該是txt_file,否則引數裡的txt_file無法獲取到所有上傳的檔案。

通過request.getSession().getServletContext().getRealPath("/WEB-INF/upload");獲取伺服器上的upload資料夾,這個資料夾是用來存放上傳的檔案。

最後轉換成圖片選取的頁面:
這裡寫圖片描述

五、處理選取框的後臺程式碼

@RequestMapping("getpdftext")
    public ModelAndView getPdfTextByRange(HttpServletRequest request,String jsonstring) throws IOException{

        String realPath = request.getSession().getServletContext().getRealPath("/WEB-INF/upload");

        System.out.println(jsonstring);

        JSONObject jsonObject=JSONObject.parseObject(jsonstring);//將json格式的字串轉換成json物件

        String fileName=jsonObject.getString("filename"); //獲取json物件中的內容
        String imgname=jsonObject.getString("imgname");
        int pageNum=Integer.parseInt(imgname.substring(0,imgname.lastIndexOf(".")));//根據1.png型別的圖片名獲取頁碼

        PdfUtil pdfUtil=new PdfUtil(realPath+File.separator+fileName);//呼叫pdf工具類,需要傳入pdf檔案的路徑

        PdfDoc pdfdoc=new PdfDoc(jsonObject.getIntValue("x"),
                                    jsonObject.getIntValue("y"),jsonObject.getIntValue("width"),
                                    jsonObject.getIntValue("height"),pageNum);//將屬性繫結到pdfdoc的物件中


        PDDocument document=pdfUtil.getdocument();

        List<String> text=pdfUtil.getpageContent(document, pdfdoc);//傳入引數獲取指定區域的內容

        ModelAndView mv=new ModelAndView("/product/pdfcontent");
        mv.addObject("content",text);

        return mv;
    }

六、資料展示頁面html

<div class="container" id="root">

        <ol>
            <c:forEach var="item" items="${content}"><li>${item}</li></c:forEach>
        </ol>
    </div>

最終資料展示:
這裡寫圖片描述