ajax获取后台流使用pdfjs显示

13 篇文章 0 订阅

网上找了好多资料都没有找到到底怎么使用文件流来让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("查询保险条款异常");}
});


附页面:

<!-- 用于预览文件时触发 -->
<div id="preview-bar" style="display:none;position: absolute;top: 0px;width: 100%;height: 100%;">


最近发现这里有一个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("查询保险条款异常");}
});



//附页面:

<!-- 用于预览文件时触发 -->
<div id="preview-bar" style="display:none;position: absolute;top: 0px;width: 100%;height: 100%;">

获取文件流接口:

/**
	 * 直接从文件服务器获取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();
        }
	}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值