1.首先先说一下这些坑:(组合套装)
这个行代码一定要注意, 而且随时打印code码,以便确认错误.
2.大致思路:
3. 先根据ID查询出来url
@RequestMapping(value="test1", produces = "text/plain;charset=UTF-8")
public void test2(HttpServletRequest request ,HttpServletResponse response){
try {
List<Map<String, Object>> queryForList = jdbcTemplate.queryForList(" select url from tb_work_record where FIND_IN_SET(wr_id,'1,2') ");
List<String> filePaths=new ArrayList<String>();
for (int i = 0; i < queryForList.size(); i++) {
filePaths.add(queryForList.get(i).get("url").toString());
}
test2(request, response, filePaths);
} catch (Exception e) {
e.printStackTrace();
}
}
4.压缩 ,调用浏览器下载,删除 web服务器临时产生zip文件
public void test2(HttpServletRequest request ,HttpServletResponse response,List<String> filePaths){
//根据url获取文件流压缩到zip文件中(重点中的重点)
String zipFilePath = copy(filePaths);
//调用浏览器下载
template(response, zipFilePath);
删除 web服务器临时产生zip文件
new File(zipFilePath);
}
5.//根据url获取文件流压缩到zip文件中
5-1.首先去ftp服务器上循环拿到文件流和文件名,
5-2.循环拿的同时循环写入到web服务器中的zip文件(可能有人要问为什么循环拿的同时要去循环写入呢? 因为每次 InputStream in = ftp.retrieveFileStream(path) 时 in都要close之后才能重新调用retrieveFileStream方法, 如果不close ,则会在第二次时in为null,或者直接假死, 但是你不能把in.close(),之后 再去调BufferedInputStream输出流写入到zip中 ,所以必须边循环拿流边循环写入到zip)
public String copy(List<String> remotePath) {
Map<String, Object> map = new HashMap<>();
FTPClient ftp = new FTPClient();
String zipBasePath = "E://upload"; //web服务器地址
String zipName =" test.zip";
String zipFilePath = zipBasePath + File.separator + zipName;//web服务器zip文件地址
try {
File zip = new File(zipFilePath);//在web服务器上创建文件
if (!zip.exists()) {
zip.createNewFile();
}
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
// 创建FTPClient对象
String host = "172.168.31.123";
Integer port = 21;
String username = "******";
String password = "*******";
// 连接FTP服务器
// 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
ftp.connect(host, port);
// 登录ftp
ftp.login(username, password);
ftp.setControlEncoding("UTF-8"); // 中文支持
ftp.enterLocalPassiveMode();//一定要加上
for (int j = 0; j < remotePath.size(); j++) {
String path = remotePath.get(j);
ftp.changeWorkingDirectory("/");
String fileName = StringUtils.substringAfterLast(remotePath.get(j), "/");
InputStream in = ftp.retrieveFileStream(path);//拿到流
map.put("io", in);
map.put("name", URLDecoder.decode(fileName, "UTF-8"));
zipFileList(zipBasePath, zipName, zipFilePath, map, zos); //没关闭in之前,先写入到zip中
in.close();
ftp.completePendingCommand();
System.out.println(ftp.getReplyCode());
}
zos.close();
} catch (Exception e) {
System.out.println(ftp.getReplyCode());
e.printStackTrace();
}
return zipFilePath;
}
6.将流依次写入到zip文件中
private void zipFileList(String zipBasePath, String zipName, String zipFilePath, Map<String, Object> filePaths,ZipOutputStream zos) throws IOException {
InputStream in=(InputStream)filePaths.get("io");
BufferedInputStream bis = new BufferedInputStream(in);
//将文件写入zip内,即将文件进行打包
zos.putNextEntry(new ZipEntry(filePaths.get("name").toString())); //这里可以修改要写入到zip中文件的名称
//写入文件的方法,同上
int size = 0;
byte[] buffer = new byte[1024]; //设置读取数据缓存大小
while ((size = bis.read(buffer)) > 0) {
zos.write(buffer, 0, size);
}
//关闭输入输出流
zos.closeEntry();
bis.close();
}
7.调用浏览器下载
public void template(HttpServletResponse response ,String downLoadPath){
try {
String fileName=downLoadPath.substring(downLoadPath.lastIndexOf("/")+1);
byte[] buffer=null;
buffer =downFileByte(downLoadPath) ;
String fileSuffixName= fileName.substring(fileName.lastIndexOf(".")+1);
response.reset(); //清除缓存
response.setContentType("application/" +fileSuffixName + ";" +"charset = UTF-8"); //设置字符集和文件后缀名
String name=id.nextId()+"";
name = new String(name.getBytes(), "ISO-8859-1");
response.setHeader("Content-Disposition","attachment; filename=" +name+"."+fileSuffixName); // 设置文件名称
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (Exception e) {
e.printStackTrace();
Log4jUtil.getLog4jUtil().error("下载zip文件异常"+e.getMessage());
}
}
8.工具类
public static byte[] downFileByte(String downLoadPath) throws Exception{
byte[] return_arraybyte=null;
InputStream ins=new FileInputStream(downLoadPath );
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int bufsize = 0;
while ((bufsize = ins.read(buf, 0, buf.length)) != -1) {
byteOut.write(buf, 0, bufsize);
}
return_arraybyte = byteOut.toByteArray();
byteOut.close();
ins.close();
return return_arraybyte;
}
感觉可以用到的连接:
code码:https://blog.csdn.net/jinhao2003/article/details/2141378
ftp主被动连接:https://www.cnblogs.com/huhaoshida/p/5412615.html
in.close坑解释连接:https://www.e-learn.cn/content/java/758171