開篇語:html
最近工做須要作一個借款合同,公司之前的合同都是經過app端下載,而後經過本地打開pdf文件,而喜歡創新的我,心想着爲何不能在線H5預覽,正是這個想法,說幹就幹,實踐過程老是艱難的,折騰了3,4天的時間,熬了兩個凌晨3,4點,其中的艱辛、以及各中的曲折、壓力只有本身能體會,項目上線後內心想着我要寫一篇博文,一是總結一下經驗,其次就是和你們分享本身這一路走來的的心得體會,歡迎吐槽!,廢話很少說,來點乾貨!java
PDF在線預覽實現:jquery
8個實如今線瀏覽PDF文件的實用插件,筆者選擇pdf.js,下面簡單介紹8個插件:git
PDFobject能夠幫助你在頁面直接嵌入pdf文件,有時候有些項目須要動態地嵌入PDF文件。PDFObject爲此而設計的,他可以快速和容易的嵌入PDF文件,PDFObject使用JavaScript來產生相同的符合標準的 標記,而後插入 到您的HTML元素的選擇。您能夠填滿整個瀏覽器窗口,或將PDF格式轉換成一個或其餘塊級元素。github
和 Google Chrome 使用的源自 Foxit 的閉源 PDF 瀏覽插件不一樣,PDF.js 是基於開放的 HTML5 及 JavaScript 技術實現的開源產品。web
pdf.js 是一個主要用於HTML5 平臺上在線閱讀PDF文檔的小插件,基於JavaScript技術編寫而成,無需任何本地技術支持。apache
pdf.js是由Mozilla Labs發佈的。他們的目標是建立一個通用的,基於標準的網絡平臺,可以解析和渲染PDF文件,並最終發佈一個PDF閱讀器擴展,毫無疑問 pdf.js 將被整合入 Gecko 成爲 Firefox 的內嵌 PDF 閱讀器,可是具體整合時間表還沒有肯定瀏覽器
jsPDF 是一個使用Javascript語言生成PDF的開源庫。你能夠在Firefox插件,服務端腳本或是瀏覽器腳本中使用它。客戶端Safari 和 iPhone Safari 支持得最好,其次是Opera和Windows下的Firefox 3等。IE暫不支持。。tomcat
jQuery Media Plugin是一款基於jQuery的網頁媒體播放器插件,它支持大部分的網絡多媒體播放器和多媒體格式,好比:Flash, Windows Media Player, Real Player, Quicktime, MP3,Silverlight, PDF。它根據當前的腳本配置,自動將a標籤替換成div,並生成object, embed甚至是iframe代碼,至於生成object仍是embed,jQuery Media會根據當前平臺自動判別,所以兼容性方面很是出色下面這段代碼是jQuery Media生成後的。網絡
下圖能夠導出爲PNG或JPG格式的靜態圖像或嵌入式靜態圖像,圖表或一個徹底互動的功能圖
Document Viewer是一個jQuery插件,可讓你在網頁中直接查看多種文件格式。文檔瀏覽器支持的文件格式:PDF文件,文本文件,代碼,圖像,音頻,視頻等。
PDF.js實踐篇
第一步 pdf.js源碼下載https://github.com/mozilla/pdf.js
源碼頁有詳細編譯步奏,最後編譯出來,將generic文件copy至tomcat webapps目錄下,瀏覽器輸入http://localhost:8080/generic/web/viewer.html,H5預覽效果以下,圖片壓縮了,實際預覽效果好不少
(我這裏覆蓋了webapps\generic\web\compressed.tracemonkey-pldi-09.pdf文件,它自帶的是英文文檔):
第二步 我集成到項目以插件的形式目錄結構以下:
第三步:編寫H5文件,這裏是將pdf.js viever.html 頁面經過Ifram嵌入進來,並經過指定file參數動態傳參,實現動態pdf文件預覽
loanPdfContract.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta name="format-detection" content="telephone=no,email=no,address=no"/>
<title>借款合同</title>
</head>
<body>
<iframe src="<c:url value="/plugin/pdfjs/generic/web/viewer.html"/>?file=<c:url value="/app/credit/loanApplication/contracts/${fileId}"/>"
width="100%" height="800">
</iframe>
</body>
</html>
第四步:編寫Controller方法,
/**
* 16.借款申請[信息確認]《合同及相關協議》-借款合同 H5接口 提供給app端調用
*
* @param userId
* @return
* @since 3.4
*/
@RequestMapping(value ="/app/credit/loanApplication/contracts/loanContract.security")
public Object loanContract(String userId,String borrowCode,String productTypeCode, Model model) {
if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(borrowCode)) {
return "app/credit/canaLoanApplication/404Error";
}
Map<String,String> returnMap = canaApplyLoanService.investmentContractTemplate(userId,borrowCode,productTypeCode);
if( BizCodeType.IS_NO.getCode().equals(returnMap.get("flag"))){
return "app/credit/canaLoanApplication/404Error";
}
model.addAttribute("fileId",returnMap.get("fileId")+".pdf");
return "app/credit/canaLoanApplication/loanPdfContract";
}
第五步:編寫Controller方法,注意這個 http head響應頭信息設置是HttpStatus.OK,和文件下載HttpStatus.CREATE頭信息有差別。
/**
* 查看PDF文件
* @param fileId
* @return
* @throws IOException
*/
@RequestMapping(value = "/app/credit/loanApplication/contracts/{fileId}.pdf", method = RequestMethod.GET)
public ResponseEntity<byte[]> loadContract(@PathVariable String fileId) throws IOException {
byte[] bytes=canaApplyLoanService.downContract(fileId);
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/pdf"));
headers.setContentLength(bytes.length);
headers.add(HttpHeaders.ACCEPT_RANGES,"bytes");
return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
}
結束語 看着這裏,PDF文件在線動態預覽基本完成,趕快體驗吧!
進階篇:Java實現PDF文件轉圖片、多個圖片合成PDF文件.
前言:
由於筆者這裏的PDF文件帶有交互式表單域,致使PDF文件沒法預覽,由於是合同PDF文件,敲章帶有簽名信息致使PDF預覽失敗,當時很是迷茫,沒有方向,後來和同城金服一架構師朋友聊天中,他給了我提示,「說是簽名的問題,須要把PDF轉成圖片」,對於筆者來講,有了思路剩下的就是實踐的事情。
由於PDF有多頁因此會轉出多張圖片,至於爲何要轉成圖片,僅僅是爲了將代簽名的交互式表單域給幹掉、由於筆者之前作過多張圖片合成一張大圖,因此當時就想,這個多張圖片合成一張PDF文件應該不是問題,對於之前較少玩PDF文件的我來講,這個想法已經很是大膽了,若是讀者的你也對PDF文件瞭解不深的話,那麼本文將很是適合你,帶你實戰PDF!
我在囉嗦一句,由於這個PDF文件簽名致使App端沒法查看,由於是第三方合同公司,因此咱們須要他們的簽名SDK文件才能預覽,
第一篇:帶你裝B,帶你飛!
說了這麼多,不來點乾貨恐怕大家都看不下去了,主流的Pdf與圖片互轉
1.PDFRenderer: 確實效率最高,可是缺乏字體支持對大多數中文pdf處理不了,這個筆者最開始使用了一下,可是報錯後來放棄了。
2.jpedal:這個是商業版本的,它官網的jar下載較慢,最開始原本打算用,好不容易csdn down下一個jar包,一運行提示jar包過時了。
3.pdfbox:筆者最終採用pdfbox,效果還不錯。以前網上說它對中文支持很差,可是筆者在pdfbox_2.0.2.jar使用過程當中都沒碰見亂碼.
第二篇:pdfbox使用
maven配置:
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.2</version>
</dependency>
java代碼:
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class PdfBoxUtil {
public static void main(String[] args) {
//pdfToImg("D:\\test\\22222.pdf","D:\\test\\22222.PNG");
pdfToImgToPdf("D:\\test\\22222.pdf","D:\\test\\3333.pdf");
}
/**
* pdf轉圖片
* @param pdfPath
* @param pngPath
*/
public static void pdfToImg(String pdfPath,String pngPath){
//將pdf裝圖片 而且自定義圖片得格式大小
File file = new File(pdfPath);
try {
PDDocument doc = PDDocument.load(file);
PDFRenderer renderer = new PDFRenderer(doc);
int pageCount = doc.getNumberOfPages();
for (int i = 0; i < pageCount; i++) {
BufferedImage image = renderer.renderImageWithDPI(i, 240);
BufferedImage srcImage = resize(image, image.getWidth(), image.getHeight());
ImageIO.write(srcImage, "PNG", new File(pngPath.replace(".",i+".")));
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* pdf轉圖片而後合成pdf
* @param pdfPath
* @param pdfOutPath
*/
public static void pdfToImgToPdf(String pdfPath,String pdfOutPath){
//將pdf裝圖片 而且自定義圖片得格式大小
File file = new File(pdfPath);
try {
PDDocument doc = PDDocument.load(file);
PDFRenderer renderer = new PDFRenderer(doc);
int pageCount = doc.getNumberOfPages();
List<BufferedImage> images=new ArrayList<BufferedImage>();
for (int i = 0; i < pageCount; i++) {
BufferedImage image = renderer.renderImageWithDPI(i, 240);
BufferedImage srcImage = resize(image, image.getWidth(), image.getHeight());
images.add(srcImage);
}
//合成圖片轉pdf
createPDFFromImage(pdfOutPath,images);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* pdf轉圖片而後合成pdf
* @param input
*/
public static byte[] pdfToImgToPdf(byte[] input){
//將pdf裝圖片 而且自定義圖片得格式大小
byte[] bytes=null;
PDDocument doc=null;
try {
doc = PDDocument.load(input);
List<BufferedImage> images=new ArrayList<BufferedImage>();
PDFRenderer renderer = new PDFRenderer(doc);
int pageCount = doc.getNumberOfPages();
for (int i = 0; i < pageCount; i++) {
BufferedImage image = renderer.renderImageWithDPI(i, 240);
BufferedImage srcImage = resize(image, image.getWidth(), image.getHeight());
images.add(srcImage);
}
bytes=createPDFFromImage(images);
} catch (IOException e) {
e.printStackTrace();
}
if(doc!=null){
try {
doc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
/**
*圖片合成pdf
* @param images
* @throws Exception
*/
public static void createPDFFromImage(String pdfOutPath,List<BufferedImage> images){
PDDocument doc = new PDDocument();
try {
PDPageContentStream contentStream;
PDPage page;
for (BufferedImage image : images) {
page = new PDPage(new PDRectangle(image.getWidth(),image.getHeight()));
doc.addPage(page);
contentStream = new PDPageContentStream(doc,page,PDPageContentStream.AppendMode.APPEND, true);
PDImageXObject pdImageXObject = JPEGFactory.createFromImage(doc,image);
contentStream.drawXObject(pdImageXObject, 0, 0, image.getWidth(),image.getHeight());
contentStream.close();
}
doc.save(pdfOutPath);
}catch (Exception ex){
ex.printStackTrace();
}finally {
if (doc != null) {
try {
doc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
*圖片合成pdf
* @param images
* @throws Exception
*/
public static byte[] createPDFFromImage(List<BufferedImage> images){
byte[] bytes=null;
ByteArrayOutputStream baos=null;
PDDocument doc = new PDDocument();
try {
PDPageContentStream contentStream;
PDPage page;
for (BufferedImage image : images) {
page = new PDPage(new PDRectangle(image.getWidth(),image.getHeight()));
doc.addPage(page);
contentStream = new PDPageContentStream(doc,page,PDPageContentStream.AppendMode.APPEND, true);
PDImageXObject pdImageXObject = JPEGFactory.createFromImage(doc,image);
contentStream.drawXObject(pdImageXObject, 0, 0, image.getWidth(),image.getHeight());
contentStream.close();
}
baos = new ByteArrayOutputStream();
doc.save(baos);
bytes=baos.toByteArray();
}catch (Exception ex){
ex.printStackTrace();
}finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (doc != null) {
try {
doc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bytes;
}
/**
* 生成圖片
* @param source
* @param targetW
* @param targetH
* @return
*/
private static BufferedImage resize(BufferedImage source, int targetW, int targetH) {
int type = source.getType();
BufferedImage target = null;
double sx = (double) targetW / source.getWidth();
double sy = (double) targetH / source.getHeight();
if (sx > sy) {
sx = sy;
targetW = (int) (sx * source.getWidth());
} else {
sy = sx;
targetH = (int) (sy * source.getHeight());
}
if (type == BufferedImage.TYPE_CUSTOM) {
ColorModel cm = source.getColorModel();
WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
boolean alphaPremultiplied = cm.isAlphaPremultiplied();
target = new BufferedImage(cm, raster, alphaPremultiplied, null);
} else {
target = new BufferedImage(targetW, targetH, type);
}
Graphics2D g = target.createGraphics();
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
g.dispose();
return target;
}
}
總結語:
到這裏筆者得和你說拜拜了,基本上將我三天研究的所有成果貢獻,其中一路艱辛,扛過多少坑,你未必知道,我只能告訴你,大多時候我心裏是奔潰的!
備註 pdf.js 我項目中的插件源碼可至我百度雲提取 連接: http://pan.baidu.com/s/1c2JVe1M 密碼: k9sc
要是你在使用過程當中遇到問題,能夠給我郵件,515173248@qq.com