这一篇解决上一篇所说的第二个问题:如何在前台打印后台生成的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(); 
		}
	}
	

7.ok,这就是从后台读取的pdf文件

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐