本功能实现的思路如下:
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
的源码,在它的最后如图:
![]()
这些属性如果不特意设置,就会使用默认值。
$("#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>
最终数据展示: