版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
最近在写项目接口,涉及到文件下载、打包压缩下载,单个文件下载还是比较简单的,多文件下载涉及到打包和压缩知识,之前也没做过,写篇博客做个简单的记录一下。闲言少叙,上代码:
如下代码是精简过后的测试代码,亲测可实际使用:
/**
* @author simons.fan
* @version 1.0
* @date 2019/7/9
* @description 文件下载controller
**/
@RestController
@RequestMapping("/file")
public class FileController {
private static final Logger logger = LoggerFactory.getLogger(FileController.class);
@Autowired
private DownLoadService downLoadService;
/**
* 单个文件下载
*
* @param fileName 真实存在的文件名
*/
@GetMapping("/down-one")
public void downOneFile(@RequestParam(value = "filename", required = false) String fileName) {
logger.info("单个文件下载接口入参:[filename={}]", fileName);
if (fileName.isEmpty()) {
return;
}
try {
downLoadService.downOneFile(fileName);
} catch (Exception e) {
logger.error("单个文件下载接口异常:{fileName={},ex={}}", fileName, e);
}
}
/**
* 批量打包下载文件
*
* @param fileName 文件名,多个用英文逗号分隔
*/
@GetMapping("/down-together")
public void downTogether(@RequestParam(value = "filename", required = false) String fileName) {
logger.info("批量打包文件下载接口入参:[filename={}]", fileName);
if (fileName.isEmpty()) return;
List<String> fileNameList = Arrays.asList(fileName.split(","));
if (CollectionUtils.isEmpty(fileNameList)) return;
try {
downLoadService.downTogetherAndZip(fileNameList);
} catch (Exception e) {
logger.error("批量打包文件下载接口异常:{fileName={},ex={}}", fileName, e);
}
}
}
/**
* @author simons.fan
* @version 1.0
* @date 2019/7/9
* @description 文件下载service
**/
@Service
public class DownLoadServiceImpl implements DownLoadService {
private static final Logger logger = LoggerFactory.getLogger(DownLoadServiceImpl.class);
@Value("${file.path}")
private String FILE_ROOT_PATH;
/**
* 单个文件下载
*
* @param fileName 单个文件名
* @throws Exception
*/
@Override
public void downOneFile(String fileName) throws Exception {
HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
File file = new File(FILE_ROOT_PATH + fileName);
if (file.exists()) {
resp.setContentType("application/x-msdownload");
resp.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(), "ISO-8859-1"));
InputStream inputStream = new FileInputStream(file);
ServletOutputStream ouputStream = resp.getOutputStream();
byte b[] = new byte[1024];
int n;
while ((n = inputStream.read(b)) != -1) {
ouputStream.write(b, 0, n);
}
ouputStream.close();
inputStream.close();
}
}
/**
* 文件批量打包下载
*
* @param fileNameList 多个文件名,用英文逗号分隔开
* @throws IOException
*/
@Override
public void downTogetherAndZip(List<String> fileNameList) throws IOException {
HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
resp.setContentType("application/x-msdownload");
//暂时设定压缩下载后的文件名字为test.zip
resp.setHeader("Content-Disposition", "attachment;filename=test.zip");
String str = "";
String rt = "\r\n";
ZipOutputStream zos = new ZipOutputStream(resp.getOutputStream());
for (String filename : fileNameList) {
str += filename + rt;
File file = new File(FILE_ROOT_PATH + filename);
zos.putNextEntry(new ZipEntry(filename));
FileInputStream fis = new FileInputStream(file);
byte b[] = new byte[1024];
int n = 0;
while ((n = fis.read(b)) != -1) {
zos.write(b, 0, n);
}
zos.flush();
fis.close();
}
//设置解压文件后的注释内容
zos.setComment("download success:" + rt + str);
zos.flush();
zos.close();
}
}
跑起来,测试,ok~
题外话
我们项目使用的是阿里云的OSS文件服务器,用过的小伙伴会发现,从OSS服务器返回的的是一个"OSSObject"对象,通过OSSObject对象,只能拿到对应的InputStream流,当时刚开始做,想法是直接将这个InputStream流写入到ZipOutputStream,一直不行。折腾半天,决定将这个InputStream流临时写入到运行服务的linux服务器,再来读这个file,当把这个文件写入到压缩对象类ZipOutputStream后,直接删除这个file即可,顺利解决我的问题。
引申阅读:
Java 导入导出功能总结:https://blog.csdn.net/fanrenxiang/article/details/80985879
记录一次mysql导入导出数据过程:https://blog.csdn.net/fanrenxiang/article/details/91491778