需求:下载合同,且支持批量下载
思路:
1.点击下载时,发送请求,携带合同的id
2.根据id,获取合同对象,根据对象获取合同文件在服务器上的路径
3.通过IO进行下载
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>
前端选择多个,在前端用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>
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)
}
});
}