【教程】帆软报表实现批量图片下载
前言
实际生产中,由于业务产生了一个小的需求,需要查询数据库中的url并批量打包下载。这个需求确实也不复杂,但是无论如何还是需要开发的,尤其是与用户交互的方面。突然想到生产中有一套帆软报表,可以实现自定义sql查询数据,那么能不能把查询结果的url交给浏览器去下载呢,经过一番探究答案是肯定的!这样简化流程后,每次只需要根据这个报表模板去修改业务sql即可满足业务要求,让只会sql的业务人员也可以实现自定义下载。
实现
如何获取查询的结果? 帆软有一套js接口可以访问查询结果集,遍历所有非空单元格就行,你也可以在自定义js中设置过滤条件来过滤你需要的url。获取和设置单元格值接口- FineReport帮助文档 - 全面的报表使用教程和学习资料应用示例里面有cpt文件可供下载修改。
获取结果之后如何下载和打包?这里需要用到两个js脚本 cdn.bootcdn.net/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js cdn.bootcdn.net/ajax/libs/jszip/3.10.1/jszip.min.js 一个用来下载,有个用来打包成zip,需要下载到帆软的安装路径中的webroot目录备用。
然后在你的报表设计器中添加一个按钮,用来下载,添加一个点击事件,引用JavaScript脚本中添加刚才下好的两个js脚本,把我给你准备的js代码粘贴进去,就可以实现下载全部图片打包了!
var _obj = $(".x-table tr");
var _length = _obj.length;
var urls = [];
for(var i = 0; i < _length; i++) {
var _td = _obj.eq(i).find("td");
for(var j = 0; j < _td.length; j++) {
var _val = _td.eq(j).text();
var _tval = $.trim(_val);
// 可以加校验:比如只收集http/https开头的内容
if(_tval !== "" && /^https?:\/\//.test(_tval)){
urls.push(_tval);
}
}
}
if(urls.length === 0){
alert("未找到任何图片URL!");
return;
}
var zip = new JSZip();
// 用IIFE+async方式支持await
(async function(){
for(let i=0; i<urls.length; i++){
try{
let response = await fetch(urls[i], {mode: 'cors'});
let blob = await response.blob();
let ext = blob.type.split('/')[1] || 'jpg';
zip.file('image_' + (i+1) + '.' + ext, blob);
}catch(e){
// 可选:console.warn(`图片下载失败: ${urls[i]}`);
}
}
zip.generateAsync({type:"blob"}).then(function(content){
saveAs(content, "images.zip");
});
})();
虽然已经初步实现了下载,但是实际中还是遇到了两个问题:1.报表默认是分页的,只能下载当前页面的内容。2.由于使用浏览器去下载,实际上会发生跨域的问题需要解决,这个在浏览器控制台可以看到报错。
分页问题:只需要在报表的查看地址后面拼写 &__bypagesize__=false ,就可以关闭默认的分页,可以存成收藏夹给业务侧使用。
跨域问题:这个需要服务端解决,一般需要一层代理或者修改服务端跨域策略。我这边环境是nginx代理的图片地址,因为是内网地址我直接改成*了,实际可以改成具体的地址。
add_header 'Access-Control-Allow-Origin' '*' always;