PDF下载与批量下载处理

需求:下载合同,且支持批量下载
思路:
1.点击下载时,发送请求,携带合同的id
2.根据id,获取合同对象,根据对象获取合同文件在服务器上的路径
3.通过IO进行下载

1.单个下载

  • 发送请求,传一个id

Controller:

/**
     * 电子签合同文件下载
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("downLoanContractPdf")
    @ResponseBody
    public void downLoanContractPdf(HttpServletRequest request, HttpServletResponse response) throws IOException{

        Long itemContractId = RequestUtil.getLong(request, "itemContractId");
        if (itemContractId != 0L){
        	// 根据合同id获取合同对象 
            LoanItemContract contract = loanItemContractService.getById(itemContractId);
            loanItemContractService.downLoanPdf(response,contract);
        }else {
            new RuntimeException("合同主键为空!");
        }
    }

service:

/**
     * PDF文件下载
     * @param response
     * @param contract
     * @throws IOException
     */
    public void downLoanPdf(HttpServletResponse response,LoanItemContract contract) throws IOException {
	
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/pdf");
		// 获取系统路径的前半部分
		String prefixPath = SystemProperties.getValue("signature.uploadContractPath");
		// 获取合同路径(后半部分)
		String srcFilePath = contract.getItemContractSrcFilePath();
		Long id = contract.getItemContractId();
		String filePath = prefixPath + srcFilePath;
		File file = new File(filePath);
		String fileName = file.getName();
		response.setHeader("Content-Disposition", "attachment; filename=" + id + fileName);

		BufferedInputStream bis = null;
		OutputStream os = null;
		FileInputStream fis = null;
		// 读取和下载合同文件pdf
		try {
			byte[] buff = new byte[1024];
			fis = new FileInputStream(file);
			bis = new BufferedInputStream(fis);
			os = response.getOutputStream();
			int i = bis.read(buff);
			while (i != -1){
				os.write(buff,0,buff.length);
				i = bis.read(buff);
				os.flush();
			}
			os.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bis != null){
				bis.close();
				fis.close();
			}
			if (os != null){
				os.close();
			}
		}
    }

前端发送请求(超链接

<a href="${ctx}/loanform/item/ContractSignManage/downLoanContractPdf.ht?itemContractId=${signManageListItem.itemContractId}" class="link edit" >下载</a>

效果:
在这里插入图片描述

2.批量下载

前端选择多个,在前端用js循环调用接口,并传入id

<a class="link add" onclick="batchDownLoanContractPdf()"><span></span>批量下载</a>

<!-- js代码 -->
<script type="text/javascript">
        // 批量下载
        function batchDownLoanContractPdf() {

            var itemContractId;
            $(".pk").each(function (i, domEle) {
                if ($(this).is(":checked")){
                    itemContractId = domEle.value;
                    window.open("/loanform/item/ContractSignManage/downLoanContractPdf.ht?itemContractId="+itemContractId)
                  }
            });
        }
    </script>

效果:会弹出四个窗口,然后出来下载框,之后窗口自动关闭
在这里插入图片描述

3.遇到的问题

1. 前端用ajax请求去下载,将id拼成json,传到后端

    @RequestMapping("batchDownLoanContractPdf")
    @ResponseBody
    public void batchDownLoanContractPdf(HttpServletRequest request, HttpServletResponse response) throws Exception{

        String data = request.getParameter("data");
        List<HashMap> hashMaps = com.alibaba.fastjson.JSONObject.parseArray(data, HashMap.class);
        QueryFilter filter = new QueryFilter();
        for (HashMap<String,Long> map : hashMaps) {
            filter.addFilter("itemContractId",map.get("itemContractId"));
            List<LoanItemContract> itemContract = loanItemContractService.getAll(filter);
            if (itemContract != null && itemContract.size()>0){
                LoanItemContract contract = itemContract.get(0);
                loanItemContractService.downLoanPdf(response,contract);
            }else {
                new RuntimeException("部分合同信息有误!");
            }
        }
    }
var jsonarray;
var jsonstr="[]";
jsonarray = eval('('+jsonstr+')');
$(".pk").each(function (i, domEle) {
	if ($(this).is(":checked")){
		var arrSplit= domEle.value;
		var arr  =
		{
			"itemContractId" : arrSplit[0]
		}
    jsonarray.push(arr);
	}
});
 $.ajax({
     url:"/loanform/item/ContractSignManage/batchDownLoanContractPdf.ht",
     type: "post",
     dataType:'json',
     async:false,
     data:{'data':JSON.stringify(jsonarray)},
     success:function(data){
     }
 });

问题: 前端传到后端的data能够接受到,后端也做了处理,但是浏览器并没有弹出下载框。后面问了才知道:ajax请求不能用来下载文件
原因: 因为response原因,一般请求浏览器是会处理服务器输出的response,例如生成png、文件下载等,然而ajax请求只是个“字符型”的请求,即请求的内容是以文本类型存放的。文件的下载是以二进制形式进行的,虽然可以读取到返回的response,但只是读取而已,是无法执行的,说白点就是js无法调用到浏览器的下载处理机制和程序。

2. 前端传一个id拼接的字符串,然后后端进行拆分,拆分后循环获取对象进行下载(用同一个response)
这个用浏览器然后传了几个id进去,结果发现只下载了一个,但是后端三个id都循环了并且调了下载的接口。
原因: 一个request只能返回对应的一个response因此,无法把多个文件使用response对象进行下载。如果不关闭ops,强行输出到一个文件中,则文件会不可读。使用Excel恢复可读,也只有第一个文件存在。
3. 前端循环id然后调接口,请求成功,下载窗口没有弹出,有响应内容
发送请求的方式及对应效果
第一种方法:

// 批量下载
function batchDownLoanContractPdf() {
	var itemContractId;
	$(".pk").each(function (i, domEle) {
		if ($(this).is(":checked")){
		itemContractId = domEle.value;
		location.href="/loanform/item/ContractSignManage/downLoanContractPdf.ht?itemContractId="+itemContractId;
     	}
	});
}

效果:只下载了一个,另外几个请求没有处理
在这里插入图片描述
第二种方法:

// 批量下载
function batchDownLoanContractPdf() {
	var itemContractId;
	$(".pk").each(function (i, domEle) {
		if ($(this).is(":checked")){
		itemContractId = domEle.value;
		$.post("/loanform/item/ContractSignManage/downLoanContractPdf.ht?itemContractId="+itemContractId)
     	}
	});
}

效果:三个请求都请求成功,状态码:200,但是没有弹出下载框,有响应内容,每一个请求重新在新的标签页打开都能下载。即重新请求一次,都能下载,由此,得出解决的办法(第三种办法)
在这里插入图片描述
响应内容:
在这里插入图片描述
总结:查阅后发现,这个是$.post()是ajax请求,区别:两者的区别

第三种方法:(解决批量下载文件,弹出多个下载框)

// 批量下载
function batchDownLoanContractPdf() {
	var itemContractId;
	$(".pk").each(function (i, domEle) {
		if ($(this).is(":checked")){
		itemContractId = domEle.value;
		window.open("/loanform/item/ContractSignManage/downLoanContractPdf.ht?itemContractId="+itemContractId)
     	}
	});
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

moonlight_Answer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值