这一篇解决上一篇所说的第二个问题:如何在前台打印后台生成的PDf文件。
在网上看了不少文章,发现可以用pdf.js去实现这个功能,pdf.js可以读取服务器上的pdf文件,实现预览、下载、打印等功能,如下图就是pdf.js提供的容器,里面的文件就是从后台读取的。
百度上很多例子都是直接读取服务器上文件的地址,也就是下面代码中的result参数直接写需要访问的pdf地址就可以了
(注:viewer.html是pdfjs提供的加载pdf文件的容器)
但是我的文件放在服务器的D盘,并没有放在项目底下,这就是需要解决的一个问题,需要后台去读取文件流返回给前台的pdf.js提供的容器,百度也有很多例子,但是在测试的时候还是遇到很多问题,百度上找到的方法是需要去改动pdf.js里面的源码,改动如下:
.(1)修改viewer.js
1)首先是源码里面的var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf' ,这是PDFJS默认的一个访问路径,删除这个变量定义;
2)然后是1899行的代码
var fileOrigin = new URL(file, window.location.href).origin;
if (fileOrigin !== viewerOrigin) {
throw new Error('file origin does not match viewer\'s');
}
修改为下面代码
if (file && 'byteLength' in file) {
} else{
var fileOrigin = new URL(file, window.location.href).origin;
if (fileOrigin !== viewerOrigin) {
throw new Error('file origin does not match viewer\'s');
}
}
(2)修改viewer.html,
在<script src="viewer.js"></script>前加入以下内容
(注意:jquery- 3.3.1.min.js也是自己加进去的)
<script src="../../js/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
//此函数是解析前台传过来的路径,取出pdf图片路径参数
function getArgsFromHref(sArgName){
// var sHref=window.location.href;
var sHref = location.search;
var args = sHref.split(sArgName+"=");
var retval = "";
//args is null
if(args[0] == sHref){
return retval;
}
var retval = args[1];
return retval;
}
//实现步骤:ajax到后台生成并保存pdf文件及pdf文件路径等信息在数据库,返回数据库id值——》
//ajax返回后调用pdfjs,并传递文件id,以便通过id获取文件路径从而读取文件流——》
//将得到的文件流在viewer.html展示
var fileid=getArgsFromHref("fileid");//前台传来的文件id
var url_file="/xxxxxx.do?fileid="+fileid;//后台访问路径,通过此后台方法得到文件流
var DEFAULT_URL = "";//默认展示的pdf,注意,删除的变量在这里重新定义
var PDFData = "";//pdf数据流
//这里的ajax就是到后台取pdf文件流
$.ajax({
type:"post",
async:false,
mimeType: 'text/plain;charset=x-user-defined',
url:url_file,
data:{'fileId':fileid},
success:function(data){
PDFData = data;
}
});
var rawLength = PDFData.length;
//转换成pdf.js能直接解析的Uint8Array类型,见pdf.js-4068
var array = new Uint8Array(new ArrayBuffer(rawLength));
for(i = 0; i < rawLength; i++) {
array[i] = PDFData.charCodeAt(i) & 0xff;
}
DEFAULT_URL = array;
</script>
5.调用示例:
我直接使用弹窗调用,result为ajax返回的文件id
6.后台读取流的方法:
网上读取流的方法很多,但是我试过的有的方法读取的流并不能再viewer.html里面解析,以致PDF显示不出来
/**
* 返回服务端PDF文件流
* @param request
* @param response
* @param user
* @throws ServletException
* @throws IOException
*/
public void getPdfFile(HttpRequest request, HttpServletResponse response, User user)
throws ServletException, IOException {
OutputStream out = response.getOutputStream();
long fileId=request.getLong("fileId");
try {
if(fileId<=0){
throw new Exception();
}
BaseDocument bd=(BaseDocument)new BaseDocument().findById(fileId);
String wholePath= Server.getUploadFilePath() + DocumentApp.getPath("FILE_PRINT_PDF")+"/"+bd.getFileName();
OutputStream os=null;
File file = new File(wholePath);
FileInputStream fileInputStream = new FileInputStream(file);
String fileName = bd.getFileName();
response.setHeader("Content-Disposition", "filename=" + fileName);
//response.setHeader("Content-disposition","filename=" + new String("证明文件.pdf".getBytes("GB2312"), "ISO-8859-1"));// 设定输出文件头
response.setContentType("application/pdf;charset=UTF-8");// 定义输出类型
//写文件
int b;
while((b=fileInputStream.read())!= -1)
{
out.write(b);
}
fileInputStream.close();
//判断pdf文件存在,且文件大小不为0
/*File file = new File(wholePath);
if(file.exists()){
byte[] data = null;
FileInputStream input = new FileInputStream(file);
data = new byte[input.available()];
input.read(data);
//response.getOutputStream().write(data);
input.close();
out.print(data);
}else{
throw new Exception();
}*/
}catch (Exception e) {
//out.print(false);
//out.write(0);
}finally {
//out.close();
}
}