应用第三方类库
"dependencies": {
"file-saver": "^2.0.5",
"jszip": "^3.10.1",
}
import JSZip from 'jszip'
import FileSaver from 'file-saver'
界面定义
<a-button type="primary" icon="download" @click="handleExportAttachment(numberTimesTxt+'候选人附件表')">下载附件</a-button>
<div style="width: 80%">
<a-progress v-if="percent>0" stroke-linecap="square" :percent="percent" :format="percent => `${parseFloat(percent.toFixed(2))}%`" />
<a-progress v-if="percent>0" stroke-linecap="square" :percent="smallPercent" :format="percent => `${curdownloadFileName}下载`" />
</div>
data定义变量
data () {
return {
percent: 0, //下载主进度条
smallPercent:0 , //下载子进度条
curdownloadFileName : '',
url: {
listAttachmentIdsByIds: "/tjb/dasTjbInfo/listAttachmentIdsByIds",
downloadUrl: "/sys/common/static/"
},
....
}
}
methods定义方法
methods: {
//将链接转化为arraybuffer文件流格式
getFile(url,parameter) {
return new Promise((resolve, reject) => {
getActionArraybuffer(url, parameter)
.then((data) => {
resolve(data)
})
.catch((error) => {
reject(error.toString())
})
})
},
handleExportAttachment(zipfileName){
let param = {};
if(this.selectedRowKeys && this.selectedRowKeys.length>0){
param['ids'] = this.selectedRowKeys.join(",")
}else{
this.$message.warning("请先选择列表条目!")
return
}
this.percent = 0
//获取下载对象信息
getAction(this.url.listAttachmentIdsByIds, param).then((res) => {
let attachements = res.result.records||res.result;
let data = attachements.map(({ id,tjdw,name,fileName}) =>
({ id,tjdw,name,fileName}))
const newData = data.filter(item=> item.fileName!=null&&item.fileName!='')
//alert(JSON.stringify(newData))
this.downloadFileToZip(newData,zipfileName)
}).finally(() => {
this.loading = false
})
},
/**
* 多线程下载数据,打成zip包
* @param newData 下载数据包
* @param zipFileName 下载zip文件名称
*/
downloadFileToZip(newData,zipFileName) {
let maxpercent = 0
this.loading = true
const zip = new JSZip()
const promises = []
//将文件添加到压缩包中
const url = this.url.downloadUrl
let attachments = []
if(this.selectedRowKeys && this.selectedRowKeys.length>0){
attachments = this.selectedRowKeys.join(",")
}
//下载数据包个数
const downNum = newData.length
newData.forEach((item,idx) => {
//url编码
let fileUrl = encodeURI(url+"/"+item.fileName)
//下载文件类型
const fileType = item.fileName.substring(item.fileName.lastIndexOf(".")+1)
//下载文件命名
let fileName = item.name+'('+item.tjdw+'推荐).'+fileType
//子进度条百分比
this.smallPercent = 0
//获取下载文件blob 数据
const promise = this.getFile(fileUrl,null).then((data) => {
this.smallPercent = 80
//压缩文件
zip.file(fileName, data, { binary: true })//文件名、文件流、是否为二进制
//设置主进度条已下载百分比,因为多线程下载,文件小的先下载完成,防止百分比来回切换
if(maxpercent<= (idx+1) / downNum *100){
maxpercent = (idx+1) / downNum *100
}
//显示当前下载的文件名
this.curdownloadFileName = fileName
//子进度条百分百
this.smallPercent = 100
//主进度条下载百分比
this.percent = maxpercent
})
//加入到压缩队列
promises.push(promise)
// this.$message.info('共'+downNum+'个文件下载,第'+(idx+1)+'文件('+fileName+")下载完成!")
})
//等待所有文件完成下载压缩,然后进行打包
Promise.all(promises)
.then(() => {
zip.generateAsync({ type: 'blob' }).then((content) => {
//利用file-saver保存文件 自定义文件名
let _zipFileName = zipFileName
if(_zipFileName == null ||_zipFileName == ''){
_zipFileName = new Date().getTime()
}
FileSaver.saveAs(
content,
_zipFileName
)
this.percent = 0
this.loading = false
})
})
.catch((err) => {
this.$message.error(err || '文件压缩失败')
this.loading = false
this.percent = 0
})
},
...
}
后端代码
@Slf4j
@RestController
@RequestMapping("/sys/common")
public class CommonController {
@GetMapping(value = "/static/**")
public void view(HttpServletRequest request, HttpServletResponse response) {
// ISO-8859-1 ==> UTF-8 进行编码转换
String imgPath = extractPathFromPattern(request);
if(oConvertUtils.isEmpty(imgPath) || imgPath=="null"){
return;
}
// 其余处理略
InputStream inputStream = null;
OutputStream outputStream = null;
try {
imgPath = imgPath.replace("..", "").replace("../","");
if (imgPath.endsWith(",")) {
imgPath = imgPath.substring(0, imgPath.length() - 1);
}
String filePath = uploadpath + File.separator + imgPath;
File file = new File(filePath);
if(!file.exists()){
response.setStatus(404);
throw new RuntimeException("文件["+imgPath+"]不存在..");
}
response.setContentType("application/force-download");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
inputStream = new BufferedInputStream(new FileInputStream(filePath));
outputStream = response.getOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, len);
}
response.flushBuffer();
} catch (IOException e) {
log.error("预览文件失败" + e.getMessage());
response.setStatus(404);
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
}
}
@RestController
@RequestMapping("/tjb/dasTjbInfo")
@Slf4j
public class DasTjbInfoController extends JeecgController<DasTjbInfo, IDasTjbInfoService> {
public Result<?> listAttachmentIdsByIds(@RequestParam(name = "ids", required = true) String ids ) {
QueryWrapper<DasTjbInfo> queryWrapper = new QueryWrapper<>();
String[] splitIds = ids.split(",");
queryWrapper.in("id",splitIds);
List<DasTjbInfo> list = dasTjbInfoService.list(queryWrapper);
return Result.OK(list);
}
}
文章介绍了在前端如何通过引入file-saver和jszip第三方库,实现文件的下载功能,并利用多线程技术进行文件的批量压缩。后端部分展示了如何提供静态资源和处理文件下载请求。
1万+

被折叠的 条评论
为什么被折叠?



