借助 iText 这个 Java 库, 我们可以将 html 文件保存为图片文件进而转换成 PDF 格式, 接下来就来具体看下 JavaScript+Java 实现 HTML 页面转为 PDF 文件保存的方法
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
需求是一个导出 pdf 的功能,多方奔走终于实现了,走了不少弯路,而且怀疑现在这个方法仍是弯的。
有个 jsPDF 插件可以在前端直接生成 pdf,很简便,但不支持 IE。
前端:
首先引入 html2canvas.js
- html2canvas(document.body, { //截图对象
- //此处可配置详细参数
- onrendered: function(canvas) { //渲染完成回调canvas
- canvas.id = "mycanvas";
- // 生成base64图片数据
- var dataUrl = canvas.toDataURL('image/png'); //指定格式,也可不带参数
- var formData = new FormData(); //模拟表单对象
- formData.append("imgData", convertBase64UrlToBlob(dataUrl)); //写入数据
- var xhr = new XMLHttpRequest(); //数据传输方法
- xhr.open("POST", "../bulletin/exportPdf"); //配置传输方式及地址
- xhr.send(formData);
- xhr.onreadystatechange = function() { //回调函数
- if (xhr.readyState == 4) {
- if (xhr.status == 200) {
- var back = JSON.parse(xhr.responseText);
- if (back.success == true) {
- alertBox({
- content: 'Pdf导出成功!',
- lock: true,
- drag: false,
- ok: true
- });
- } else {
- alertBox({
- content: 'Pdf导出失败!',
- lock: true,
- drag: false,
- ok: true
- });
- }
- }
- }
- };
- }
- });
- //将以base64的图片url数据转换为Blob
- function convertBase64UrlToBlob(urlData) {
- //去掉url的头,并转换为byte
- var bytes = window.atob(urlData.split(',')[1]);
- //处理异常,将ascii码小于0的转换为大于0
- var ab = new ArrayBuffer(bytes.length);
- var ia = new Uint8Array(ab);
- for (var i = 0; i < bytes.length; i++) {
- ia[i] = bytes.charCodeAt(i);
- }
- return new Blob([ab], {
- type: 'image/png'
- });
- }
兼容性:Firefox 3.5+, Chrome, Opera, IE10+
不支持:iframe,浏览器插件,Flash
跨域图片需要在跨域服务器 header 加上允许跨域请求
- access-control-allow-origin: * access-control-allow-credentials: true
svg 图片不能直接支持,已经有补丁包了,不过我没有试过。
IE9 不支持 FormData 数据格式,也不支持 Blob,这种情况下将 canvas 生成的 64base 字符串去掉 url 头之后直接传给后台,后台接收之后:
- String base64 = Img.split(",")[1];
- BASE64Decoder decode = new BASE64Decoder();
- byte[] imgByte = decode.decodeBuffer(base64);
后端:
导入 itext jar 包(官方下载地址:https://sourceforge.net/projects/itext/)
- @RequestMapping("/exportPdf")
- public @ResponseBody void exportPdf(MultipartHttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
- ResultData result = new ResultData(); //自定义结果格式
- String filePath = "c:\\exportPdf2.pdf";
- String imagePath = "c:\\exportImg2.bmp";
- Document document = new Document();
- try{
- Map getMap = request.getFileMap();
- MultipartFile mfile = (MultipartFile) getMap.get("imgData"); //获取数据
- InputStream file = mfile.getInputStream();
- byte[] fileByte = FileCopyUtils.copyToByteArray(file);
- FileImageOutputStream imageOutput = new FileImageOutputStream(new File(imagePath));//打开输入流
- imageOutput.write(fileByte, 0, fileByte.length);//生成本地图片文件
- imageOutput.close();
- PdfWriter.getInstance(document, new FileOutputStream(filePath)); //itextpdf文件
- // document.setPageSize(PageSize.A2);
- document.open();
- document.add(new Paragraph("JUST TEST ..."));
- Image image = Image.getInstance(imagePath); //itext-pdf-image
- float heigth = image.getHeight();
- float width = image.getWidth();
- int percent = getPercent2(heigth, width); //按比例缩小图片
- image.setAlignment(Image.MIDDLE);
- image.scalePercent(percent+3);
- document.add(image);
- document.close();
- result.setSuccess(true);
- operatelogService.addOperateLogInfo(request, "导出成功:成功导出简报Pdf");
- }catch (DocumentException de) {
- System.err.println(de.getMessage());
- }
- catch (Exception e) {
- e.printStackTrace();
- result.setSuccess(false);
- result.setErrorMessage(e.toString());
- try {
- operatelogService.addOperateLogError(request, "导出失败:服务器异常");
- } catch (Exception e1) {
- e1.printStackTrace();
- }
- }
- response.getWriter().print(JSONObject.fromObject(result).toString());
- }
- private static int getPercent2(float h, float w) {
- int p = 0;
- float p2 = 0.0f;
- p2 = 530 / w * 100;
- p = Math.round(p2);
- return p;
- }
iText 是著名的开放源码的站点 sourceforge 一个项目,是用于生成 PDF 文档的一个 java 类库。
处理速度快,支持很多 PDF"高级" 特性。
来源: http://www.phperz.com/article/17/0227/265301.html