一、url请求下载
态静态资源下载:
- window.location.href=URL
- window.open(URL)
- 创建 a 标签并指定 a.href=URL 模拟点击进行下载
二、axios请求下载(二进制下载)
携带token,防止url参数过长
将请求的返回结果 XMLHttpRequest.responseType 设置为 blob 用 URL.createObjectURL()
和 Blob 处理返回二进制流 然后使用 a 标签模拟点击下载
1.后台关键代码
controller
/**
* 根据文件目录id查询目录下所以文件以zip方式下载
*
* @return 结果
*/
@GetMapping("${pdc.path-prefix}/share/dir/files")
@ApiOperation(value = "根据目录id查询zip文件流", notes = "根据目录id查询zip文件流")
void getDirFilesStream(@RequestParam("dirId") Long dirId,@RequestParam("dirName") String dirName, @RequestParam("source") String source){
userShareService.getDirFilesStream(dirId, dirName, source, this.response);
}
service
@Override
public void getDirFilesStream(Long dirId, String dirName, String source, HttpServletResponse response) {
try {
if (dirId == null || StringUtils.isEmpty(source)) {
throw new RuntimeException("导出文件失败,请联系管理员!");
}
//1.递归查找所有文件夹和文件
List<OssShareDirVO> dirFilesList = this.getShareDirList(new OssShareDirQuery().setBizId(dirId).setSource(source));
getDirFiles(dirFilesList, source);
String zipName = dirName + "_" + ".zip";
File zipFile = File.createTempFile("temp" + System.currentTimeMillis(), "zip");//创建zip临时文件
compressZip(dirFilesList, zipFile, dirName, true);
//下载zip文件
CompressUtil.downloadZip(response, zipName, zipFile);
} catch (IOException e) {
e.printStackTrace();
}
}
utils
/**
* 下载zip
*
* @param response
* @param zipName 浏览器header中zip名称
* @param zipFile zipFile文件
*/
public static void downloadZip(HttpServletResponse response, String zipName, File zipFile) {
//下载文件
try {
response.setCharacterEncoding("utf-8");
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;FileName=" + zipName);
ServletOutputStream out = response.getOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(zipFile);
while ((len = fis.read(buffer)) > 0) {
out.write(buffer, 0, len);
out.flush();
}
out.close();
fis.close();
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
}
2.前端js
/**
* 根据文件目录id查询目录下所以文件以zip方式下载
* @param id
* @returns {*}
*/
export function getDirFilesStream(dirId,dirName,source) {
return axios({
url: `${api.share}` + '/dir/files?dirId='+dirId+'&dirName='+dirName+'&source='+source,
method: 'get',
responseType: 'blob'
}).then((res) => {
if (res.status === 200){
const blob = new Blob([res.data], { type: 'application/zip'})
if ('download' in document.createElement('a')){
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = dirName
link.click()
// 释放内存
URL.revokeObjectURL(url)
} else {
// ie10下载
navigator.msSaveOrOpenBlob(blob, downloadName)
}
return true
}
})
三、XMLHttpRequest请求下载(二进制下载)
1.后台controller
/**
*
* @param docIds
* @param response
* @param redirectAttributes
* @throws IOException
*/
@RequestMapping(value = "batchPrint/download", method = RequestMethod.POST)
@RequiresPermissions("pdc:pdcDocument:print")
@ResponseBody
public void batchDownload(String[] docIds, HttpServletResponse response, HttpServletRequest request, RedirectAttributes redirectAttributes) throws IOException {
try {
//1.查询需要导出的文档集
List<PdcDocument> allDoc = new ArrayList<>();
for (String docId : docIds) {
allDoc.add(pdcDocumentService.get(docId));
}
//2.生成临时压缩文件zip
String zipName = new DateTime().toString("yyyyMMddHHmmssSSS") + ".zip";
File downloadFile = new File(downloadPath);
if (!downloadFile.isDirectory()) {
downloadFile.mkdirs();
}
String fileZipPath = downloadPath + zipName;
//3.定义Zip文件输出流
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(fileZipPath));
List<MyZipEntry> myZipEntries = new ArrayList<>();
//4.遍历文档集,往zip逐个写入文档数据
FTPClient ftpClient = tcmFtpUtils.getFTPClient();
for (PdcDocument doc : allDoc) {
//4.1获取文档数据流
String filePath = doc.getFilePath();
String pdfPath = ""; //文档完整路径
if (!filePath.toLowerCase().endsWith(".pdf")) {
pdfPath = filePath.substring(0, filePath.lastIndexOf('.')) + ".pdf";
} else {
pdfPath = filePath;
}
try {
InputStream inputStream = tcmFtpUtils.readFile(ftpClient, pdfPath, TcmFTPUtils.UTF8);
if (inputStream != null) {
String fileName = filePath.substring(pdfPath.lastIndexOf('/') + 1);
MyZipEntry ze = new MyZipEntry(fileName);
//3.4将文档数据流写入zip(去重)
if (!myZipEntries.contains(ze)) {
myZipEntries.add(ze);
zos.putNextEntry(ze);
IOUtils.copy(inputStream, zos); //压缩文件保存到本地zip
zos.closeEntry();
inputStream.close();
} else {
logger.warn(String.format("pdf文件重复:%s。", pdfPath));
}
} else {
logger.warn(String.format("获取源文件失败:%s。", pdfPath));
}
} catch (Exception e) {
logger.error(String.format("压缩zip文件失败:%s。", e.getMessage()));
} finally {
//多个文件一定要
ftpClient.completePendingCommand();
}
}
//5.关闭zip压缩输出流
zos.close();
//6.下载压缩好的zip文件
try {
response.setContentType("application/x-download");//告知浏览器下载文件,而不是直接打开,浏览器默认为打开
response.setHeader("Content-Disposition", "attachment;filename=\"" + zipName + "\"");//下载文件的名称
//将打包好的zip下载到用户浏览器
InputStream in = new FileInputStream(fileZipPath);
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
IOUtils.copy(in, out);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
} catch (IOException e) {
logger.error(String.format("导出失败:%s。", e.getMessage()));
} finally {
FileUtils.deleteQuietly(new File(fileZipPath)); //删除服务器本地产生的临时压缩文件
}
//6.导出日志
DocumentOperationLogUtils.saveLog(request, allDoc, "导出");
} catch (Exception e) {
logger.error(String.format("导出失败:%s。", e.getMessage()));
addMessage(redirectAttributes, "导出失败!失败信息:" + e.getMessage());
}
}
2.前端js
function downloadDocs(docIds) {
var xhr = new XMLHttpRequest();
xhr.open("post","/PDCSite/a/pdc/pdcDocument/batchPrint/download",true);
xhr.responseType="blob";
xhr.onload=function(){
if(this.status == 200){
const blob = new Blob([this.response],{type:'application/zip'})
if('download' in document.createElement('a')){
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = "文档下载";
link.click();
// 释放内存
URL.revokeObjectURL(url);
}else{
//IE10下载
navigator.msSaveOrOpenBlob(blob,"文档下载");
}
}
}
var fd = new FormData()
fd.append("docIds",docIds)
xhr.send(fd);
}
}```