Java 下载多个文件打成zip压缩包
Java 下载多个文件打成zip压缩包
准备:
- 单个文件下载接口
- 文件下载地址
- RestTemplate运用
思路:
- 文件下载是文件读入与输出(字节流)的过程。
- 调用rpc接口,获取多个文件字节流
- 创建一个zip文件输出流,将多个文件字节流输出到zip,生成一个临时zip文件
- 创建新的输入流读zip文件字节,将字节流输出。(文件下载)
- 删除zip临时文件,并关闭流
需求场景:
- 下载勾选的多个文件,打成一个zip包,下载。 下载的文件可以通过rpc或者本地文件下载。
说明:
- 通过现有接口,下载文件在打成zip包,或者自己读文件打成zip包,思路是一样的。
1.demo
FileController.class
@RestController
@RequestMapping("/file")
public class FileController {
@Resource
private IFileService fileService;
@GetMapping("/indirectDown")
public void indirectDownFile(@RequestParam("fileId") String fileId,HttpServletResponse response) throws IOException {
fileService.indirectDownFile(fileId,response);
}
@GetMapping("/directDown")
public void directDownFile(@RequestParam("fileIds") List<String> fileIds, HttpServletResponse response) throws IOException {
fileService.directDownFile(fileIds,response);
}
}
IFileService.class
public interface IFileService {
void indirectDownFile(String fileId,HttpServletResponse response) throws IOException;
void directDownFile(List<String> fileIds, HttpServletResponse response) throws IOException;
}
IFileService.class
@Service
public class IFileServiceImpl implements IFileService {
@Resource
private RestTemplate restTemplate;
@Value("${tmpFilePath}")
private String tmpFilePath;
@Override
public void indirectDownFile(String fileId,HttpServletResponse response) throws IOException {
File file = new File("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\壁纸\\"+fileId+".jpg");
InputStream is = new FileInputStream(file);
byte[] bs = new byte[1024];
int len = -1;
ServletOutputStream outputStream = response.getOutputStream();
response.setContentType("application/msexcel;charset=utf-8");//定义输出类型
response.setHeader("Content-Disposition","attachment;fileName=" +fileId+ ".jpg");
while((len = is.read(bs)) != -1){
outputStream.write(bs,0, len);
outputStream.flush();
}
}
@Override
public void directDownFile(List<String> fileIds, HttpServletResponse response) throws IOException {
// 1.设置相应头,下载所有需要的文件,获取byte字节流,获取输出流对象
response.setContentType("application/msexcel;charset=utf-8");//定义输出类型
response.setHeader("Content-Disposition","attachment;fileName=1.zip");
ServletOutputStream os = response.getOutputStream();
List<byte[]> ret = downloadFiles(fileIds);
// 2.封装zip压缩包,需要先创建文件夹
File file = new File(tmpFilePath);
if(!file.isDirectory()){
file.mkdirs();
}
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(tmpFilePath+File.separator+"1.zip"));
InputStream is = new FileInputStream(tmpFilePath+File.separator+"1.zip");
for (byte[] bytes : ret) {
String fileName = UUID.randomUUID().toString();
zipOut.putNextEntry(new ZipEntry(fileName+".jpg"));
zipOut.write(bytes,0,bytes.length);
zipOut.flush();
}
zipOut.close();
//3.将zip输出
byte[] zipBytes = new byte[1024];
int len = -1;
while((len = is.read(zipBytes)) != -1){
os.write(zipBytes,0,len);
}
os.flush();
os.close();
is.close();
//4.删除生成的临时zip
File tmpZip = new File(tmpFilePath+File.separator+"1.zip");
tmpZip.delete();
}
private List<byte[]> downloadFiles(List<String> fileIds) {
List<byte[]> ret = new ArrayList<>();
fileIds.stream().forEach(fileId->{
String url = "http://localhost:8081/file/indirectDown?fileId="+fileId;
byte[] bs = restTemplate.getForObject(url, byte[].class);
ret.add(bs);
});
return ret;
}
}
SpringBoot启动类:RestDownloadApp
主要是注册一个RestTemplate bean,没有其它特殊需要说明的。
@SpringBootApplication
public class RestDownloadApp {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(RestDownloadApp.class,args);
}
}
application.yml
配置文件中的内容根据需要进行修改。如果端口号变了,记得要在IFileServiceImpl
中修改Rpc 接口的地址。端口修改一致就行。
server:
port: 8081
#文件下载 暂存目录
tmpFilePath: E:\\tmpFile
2.说明
如果是本地服务文件下载就可以省略rpc获取文件流的哪一步了。直接读取本地文件流。构建ZipEntry
对象。赋值到zip
输出流中。
其它部分不需要改变。