网上找了好多资料都没有找到到底怎么使用文件流来让pdfjs显示。
经过高手的指导,终于弄出来了。遂作下记录,供大家参考。
需求:从文件服务器获得文件(pdf)让前端页面显示
首先我们需要构建好的pdfjs包,直接放在项目下面,我放这儿:
下载地址:http://download.csdn.net/detail/muluo7fen/9921114
后台的框架springmvc4,hibernate(这里的主要代码没影响)
@RequestMapping("/previewPdf.do")
@ResponseBody
public String previewPDF(HttpServletRequest request,
HttpServletResponse response,String fileId){
InputStream input = null;
OutputStream out = null;
String fileName = "";
try {
…… //查询文件
if(hm!=null){
//查到文件就复制到服务器上
if("SUCCESS".equals(hm.get("STATUS").toString())){
File file = (File)hm.get("file");
//这里在服务器上创建新的文件
File pdf = new File(request.getSession().getServletContext().getRealPath("/")+"file/"+file.getName());
out = new FileOutputStream(pdf);
input = new FileInputStream(file);
byte[] b = new byte[input.available()];
int len = 0;
while ((len = input.read(b)) != -1){
out.write(b, 0, len);
out.flush();
}
input.close();
out.close();
//复制完了文件,把应用服务器上的文件路径发给前台
fileName = file.getName();
}else{
System.out.println(hm.get("ERROR_MESSAGE").toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
前端:
$.ajax({
type : 'POST',
url : 'xxx.do',
dataType : 'JSON',
data : {
'fileId' : fid,
},
success : function(data){
if(data){
$('.navbar-header').hide();
$('#preview-btn').show();
$('#preview-bar').show();
//这里是使用iframe显示的,因为需求要嵌入页面而不是直接打开新页面,总之只要把我们服务器上的路径作为参数给viewer.html?file=
//就可以显示了
$('#file_preview').attr('src','/pd/res/pdfJs/generic/web/viewer.html?file=/pd/file/'+data);
}
},
error : function(){alert("查询保险条款异常");}
});
附页面:
最近发现这里有一个bug,当我们使用iframe显示pdf的时候,实际上是等于加载了一个新页面,viewer.html。
所以,如果我们在这里需要使用历史记录的回退功能例如history.back()这样的方法,会出现第一次回退的是我们iframe显示pdfjs里头的页面,
而不是外部父页面的回退功能,所以如果要忽略iframe里面的影响,我们需要在加载src前,为html添加iframe元素,此时直接把src赋值应该就可以了,
然后当我们不需要预览了,就把iframe删掉。(这个我是这样,可以每次在创建元素的时候删,可能也是可以,可以试试)
看到这里,我都觉得对不起这个标题了,根本不是直接用流好吗!?
事隔多月,我们进入正题,经过正式环境的部署测试,由于使用了nginx进行负载均衡,主节点是存静态文件,导致上面的方法在获取pdf文件的时候直接去主节点拿了,结果当然没有,因为存在了各个应用服务器上嘛。
通过众多博客微博中大浪淘沙,发现可以直接用流的好文:https://www.cnblogs.com/vijayblog/p/6126335.html
先谈一下整体的思路:
首先编写后台获取pdf文件流的代码,完成后直接用前端测试通过,这里的文件是写死的本地文件,发现可行。
(前端直接把获取流的接口地址赋值给src)
接下来将文件换成文件服务器上的文件,同样可行。
下面要面对的问题是怎么传文件id这个参数了。
当前pdfjs的页面地址是:$('#file_preview').attr('src','/pd/res/pdfJs/generic/web/viewer.html?file=xxx.do);
在这个接口地址后面,我们不能直接再加一个参数,viewer.html?file=xxx.do?fileId=xxx,这样就搞笑了。
网上也看了有人去改pdf.js或者自己添加代码,都太麻烦了。
我直接通过一个接口得到viewer.html?file=这串后面的地址,这个地址是通过URLEncoder.encoder("地址?参数=xxx","utf-8")转码就行了
具体代码:
后台获取链接地址的接口:
/**
* 生成待预览的url地址
* 该地址用于pdfjs的file参数值
* @param request
* @param response
* @param fileId
* @return
*/
@RequestMapping("/previewPdf.do")
@ResponseBody
public OperateResult previewPdfUrl(HttpServletRequest request,
HttpServletResponse response,String fileId){
OperateResult result = new OperateResult();
try {
StringBuffer serverPath = request.getRequestURL();
int start = serverPath.indexOf("product/previewPdf.do");
serverPath.replace(start, serverPath.length(), "getPdfFile.do");
serverPath.append("?fileId="+fileId);
System.out.println("预览地址:"+serverPath.toString());
String urlPath = URLEncoder.encode(serverPath.toString(),"utf-8");
result.setStatus(0);
result.setData(urlPath);
} catch (Exception e) {
result.setStatus(1);
result.setMessage("查询条款异常");
e.printStackTrace();
}
return result;
}
前端代码:
$.ajax({
type : 'POST',
url : 'xxx.do',
dataType : 'JSON',
data : {
'fileId' : fid,
},
success : function(data){
if(data){
$('.navbar-header').hide();
$('#preview-btn').show();
$('#preview-bar').show();
//这里是使用iframe显示的,因为需求要嵌入页面而不是直接打开新页面,总之只要把我们服务器上的路径作为参数给viewer.html?file=
//就可以显示了
$('#file_preview').attr('src','/pd/res/pdfJs/generic/web/viewer.html?file='+data.data);//!!!这里就是一个后台获取流的接口带参数的
}
},
error : function(){alert("查询保险条款异常");}
});
//附页面:
获取文件流接口:
/**
* 直接从文件服务器获取pdf文件预览
* 用文件流交给前端pdfjs的view.html?fileId=请求.do
* @param request
* @param response
* @param fileId
*/
@RequestMapping("/getPdfFile.do")
public void pdfjs1(HttpServletRequest request,
HttpServletResponse response,String fileId){
byte[] data = null;
try {
File file = new File("text.pdf")//这一步自己根据实际情况获取文件,项目代码不方便贴出来,嘿嘿嘿
FileInputStream input = new FileInputStream(file);
data = new byte[input.available()];
input.read(data);
response.getOutputStream().write(data);
input.close();
} catch (Exception e) {
e.printStackTrace();
}
}