使用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>
最終資料展示: