controller
@ApiOperation("通过下载url批量打包zip下载")
@PostMapping("batchDownloadFile")
public void batchDownloadFile(@RequestBody List<String> urlList){
log.debug("通过下载url批量打包zip下载 入参 {} ", urlList.toString());
if (CollectionUtils.isEmpty(attachmentVoList)){
return;
}
fileService.batchDownloadFile(urlList,this.getResponse(),this.getRequest());
}
service接口
/**
* 通过下载url批量打包zip下载
* @param urlList需下载的文件信息(下载地址,文件名称)
* @param response 响应
*/
void batchDownloadFile(List<String> urlList, HttpServletResponse response, HttpServletRequest request);
service实现类
/** 需要压缩的文件夹 */
private final static String downloadDir = "download";
/** 打包后的文件夹 */
private final static String downloadZip = "downloadZip";
/**
* 重载通过下载url批量打包zip下载
* @param urlList需下载的文件信息(下载地址,文件名称)
* @param response 响应
*/
@Override
public void batchDownloadFile(List<String> urlList, HttpServletResponse response, HttpServletRequest request) {
//下载文件
urlList.stream().forEach(this::downloadFile);
//把下载的图片文件夹压缩
downloadZip(request, response);
}
/**
* 下载文件
* @param attachmentVo 文件
*/
public void downloadFile(String fileUrl){
InputStream inputStream = null;
OutputStream outputStream = null;
try {
//获取连接
URL url = new URL(fileUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setConnectTimeout(3*1000);
//设置请求头
connection.setRequestProperty(
"User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36");
//获取输入流
inputStream = connection.getInputStream();
// 创建一个文件夹 download
File fileDir = new File(downloadDir);
if(!fileDir.exists()){
fileDir.mkdir();
}
// 将文件下载到download文件夹下 文件下载保存路径
String filePath = downloadDir + "/" + 此处为文件名称,可通过传入也可通过地址字符串截取;
// 通过路径创建文件
File file = new File(filePath);
//创建文件,存在覆盖
file.createNewFile();
outputStream = new FileOutputStream(file);
int len = 0;
byte[] buf = new byte[1024];
while ((len = inputStream.read(buf, 0, 1024)) != -1) {
outputStream.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
log.error("文件下载出错:" + e);
} finally {
try {
if (outputStream != null) {
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
log.error("关闭流出错:" + e);
}
}
}
/**
* 下载压缩包
*/
public void downloadZip(HttpServletRequest request, HttpServletResponse res) {
OutputStream out = null;
File zip = null;
File fileDir = null;
ZipOutputStream zos = null;
BufferedInputStream bis = null;
try{
//多个文件进行压缩,批量打包下载文件 创建压缩文件需要的空的zip包
String zipName = "zip文件";
// zip文件存放路径
String zipFilePath = downloadZip + File.separator + zipName + ".zip";
fileDir = new File(downloadZip);
if(!fileDir.exists()){
fileDir.mkdir();
}
//压缩文件
zip = new File(zipFilePath);
//创建文件,存在覆盖
zip.createNewFile();
//创建zip文件输出流
zos = new ZipOutputStream(new FileOutputStream(zip));
this.zipFile(downloadDir, zos);
if (zos != null){
zos.close();
}
//将打包后的文件写到客户端,输出的方法同上,使用缓冲流输出
bis = new BufferedInputStream(new FileInputStream(zipFilePath));
byte[] buff = new byte[bis.available()];
bis.read(buff);
//IO流实现下载的功能
res.setCharacterEncoding("UTF-8");
// 设置下载内容类型application/octet-stream(二进制流,未知文件类型);
res.setContentType("application/octet-stream;charset=UTF-8");
//防止文件名乱码
String userAgent = request.getHeader("USER-AGENT");
//火狐浏览器
if (userAgent.contains("Firefox") || userAgent.contains("firefox")) {
zipName = new String(zipName.getBytes(), "ISO8859-1");
} else {
//其他浏览器
zipName = URLEncoder.encode(zipName, "UTF-8");
}
//设置下载的压缩文件名称
res.setHeader("Content-disposition", "attachment;filename=" + zipName);
//创建页面返回方式为输出流,会自动弹出下载框
out = res.getOutputStream();
//输出数据文件
out.write(buff);
FileUtil.deleteDir(downloadDir);
}catch(Exception e) {
log.error("压缩包下载出错:" + e);
}finally {
try{
if (zos != null){
zos.flush();
zos.close();
}
if (bis != null){
bis.close();
}
if(out != null){
out.flush();
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
// // 删除zip文件
// zip.delete();
// // 删除zip的文件夹
// fileDir.delete();
FileUtil.deleteDir(downloadZip);
}
}
/**
* 压缩文件
* @param filePath 需要压缩的文件夹
* @param zos zip文件输出流
*/
private void zipFile(String filePath,ZipOutputStream zos) {
//根据文件路径创建文件
File inputFile = new File(filePath);
if(inputFile.exists()) {
//判断是否属于文件,还是文件夹
if (inputFile.isFile()) {
BufferedInputStream bis = null;
try{
//创建输入流读取文件
bis = new BufferedInputStream(new FileInputStream(inputFile));
//将文件写入zip内,即将文件进行打包
zos.putNextEntry(new ZipEntry(inputFile.getName()));
//写入文件的方法,同上
int size = 0;
//设置读取数据缓存大小
byte[] buffer = new byte[1024];
while ((size = bis.read(buffer)) > 0) {
zos.write(buffer, 0, size);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭输入输出流
try {
zos.closeEntry();
//关闭输入输出流
if (bis != null){
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
//如果是文件夹,则使用递归的方法获取文件,写入zip
try {
File[] files = inputFile.listFiles();
if (ObjectUtils.isNotEmpty(files)){
for (File fileTem : files) {
zipFile(fileTem.toString(),zos);
}
}
} catch (Exception e) {
log.error("压缩文件出错:" + e);
}
}
}
}
FileUtil 工具类
package com.gremlin.common.core.utils;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
* File工具类,扩展 hutool 工具包
* @author fremlin
* @date 2013-03-08
*/
public class FileUtil extends cn.hutool.core.io.FileUtil {
/**
* 定义GB的计算常量
*/
private static final int GB = 1024 * 1024 * 1024;
/**
* 定义MB的计算常量
*/
private static final int MB = 1024 * 1024;
/**
* 定义KB的计算常量
*/
private static final int KB = 1024;
/**
* 格式化小数
*/
private static final DecimalFormat DF = new DecimalFormat("0.00");
/**
* MultipartFile转File
*/
public static File toFile(MultipartFile multipartFile){
// 获取文件名
String fileName = multipartFile.getOriginalFilename();
// 获取文件后缀
String prefix="."+getExtensionName(fileName);
File file = null;
try {
// 用uuid作为文件名,防止生成的临时文件重复
file = File.createTempFile(IdUtil.simpleUUID(), prefix);
// MultipartFile to File
multipartFile.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
/**
* 获取文件扩展名,不带 .
*/
public static String getExtensionName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return filename;
}
/**
* Java文件操作 获取不带扩展名的文件名
*/
public static String getFileNameNoEx(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length()))) {
return filename.substring(0, dot);
}
}
return filename;
}
/**
* 文件大小转换
*/
public static String getSize(long size){
String resultSize;
if (size / GB >= 1) {
//如果当前Byte的值大于等于1GB
resultSize = DF.format(size / (float) GB) + "GB ";
} else if (size / MB >= 1) {
//如果当前Byte的值大于等于1MB
resultSize = DF.format(size / (float) MB) + "MB ";
} else if (size / KB >= 1) {
//如果当前Byte的值大于等于1KB
resultSize = DF.format(size / (float) KB) + "KB ";
} else {
resultSize = size + "B ";
}
return resultSize;
}
/**
* inputStream 转 File
*/
public static File inputStreamToFile(InputStream ins, String name) throws Exception{
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
if (file.exists()) {
return file;
}
OutputStream os = new FileOutputStream(file);
int bytesRead;
int len = 8192;
byte[] buffer = new byte[len];
while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
return file;
}
/**
* 将文件名解析成文件的上传路径
*/
public static File upload(MultipartFile file, String filePath) {
//String name = getFileNameNoEx(file.getOriginalFilename());
String suffix = getExtensionName(file.getOriginalFilename());
StringBuffer nowStr = fileRename();
try {
String fileName = nowStr + "." + suffix;
String path = filePath + fileName;
// getCanonicalFile 可解析正确各种路径
File dest = new File(path).getCanonicalFile();
// 检测是否存在目录
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
// 文件写入
file.transferTo(dest);
return dest;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String fileToBase64(File file) throws Exception {
FileInputStream inputFile = new FileInputStream(file);
String base64;
byte[] buffer = new byte[(int)file.length()];
inputFile.read(buffer);
inputFile.close();
base64=Base64.encode(buffer);
return base64.replaceAll("[\\s*\t\n\r]", "");
}
/**
* 导出excel
*/
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
String tempPath =System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
File file = new File(tempPath);
BigExcelWriter writer= ExcelUtil.getBigWriter(file);
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(list, true);
//response为HttpServletResponse对象
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
response.setHeader("Content-Disposition","attachment;filename=file.xlsx");
ServletOutputStream out=response.getOutputStream();
// 终止后删除临时文件
file.deleteOnExit();
writer.flush(out, true);
//此处记得关闭输出Servlet流
IoUtil.close(out);
}
public static String getFileType(String type) {
String documents = "txt doc pdf ppt pps xlsx xls docx";
String music = "mp3 wav wma mpa ram ra aac aif m4a";
String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
if(image.contains(type)){
return "pic";
} else if(documents.contains(type)){
return "txt";
} else if(music.contains(type)){
return "music";
} else if(video.contains(type)){
return "vedio";
} else {
return "other";
}
}
public static void checkSize(long maxSize, long size) {
// 1M
int len = 1024 * 1024;
if(size > (maxSize * len)){
System.out.println("文件超出规定大小");
}
}
/**
* 判断两个文件是否相同
*/
public static boolean check(File file1, File file2) {
String img1Md5 = getMd5(file1);
String img2Md5 = getMd5(file2);
return img1Md5.equals(img2Md5);
}
/**
* 判断两个文件是否相同
*/
public static boolean check(String file1Md5, String file2Md5) {
return file1Md5.equals(file2Md5);
}
private static byte[] getByte(File file) {
// 得到文件长度
byte[] b = new byte[(int) file.length()];
try {
InputStream in = new FileInputStream(file);
try {
in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
return b;
}
private static String getMd5(byte[] bytes) {
// 16进制字符
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(bytes);
byte[] md = mdTemp.digest();
int j = md.length;
char[] str = new char[j * 2];
int k = 0;
// 移位 输出字符串
for (byte byte0 : md) {
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 下载文件
* @param request /
* @param response /
* @param file /
*/
public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit){
response.setCharacterEncoding(request.getCharacterEncoding());
response.setContentType("application/octet-stream");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
response.setHeader("Content-Disposition", "attachment; filename="+file.getName());
IOUtils.copy(fis,response.getOutputStream());
response.flushBuffer();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
if(deleteOnExit){
file.deleteOnExit();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static String getMd5(File file) {
return getMd5(getByte(file));
}
/**
* 读取json文件,返回json串
* @param fileName
* @return
*/
public static String readJsonFile(String fileName) {
String jsonStr = "";
try {
File jsonFile = new File(fileName);
FileReader fileReader = new FileReader(jsonFile);
Reader reader = new InputStreamReader(new FileInputStream(jsonFile),"utf-8");
int ch = 0;
StringBuffer sb = new StringBuffer();
while ((ch = reader.read()) != -1) {
sb.append((char) ch);
}
fileReader.close();
reader.close();
jsonStr = sb.toString();
return jsonStr;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static BufferedImage inputImage(MultipartFile file) {
BufferedImage srcImage = null;
try {
FileInputStream in = (FileInputStream) file.getInputStream();
srcImage = javax.imageio.ImageIO.read(in);
} catch (IOException e) {
System.out.println("读取图片文件出错!" + e.getMessage());
}
return srcImage;
}
/**
* 自动调节精度(经验数值)
*
* @param size 源图片大小
* @return 图片压缩质量比
*/
public static float getAccuracy(long size) {
float accuracy;
if (size < 400) {
accuracy = 0.85f;
} else if (size < 900) {
accuracy = 0.75f;
} else if (size < 2047) {
accuracy = 0.6f;
} else if (size < 3275) {
accuracy = 0.44f;
} else {
accuracy = 0.4f;
}
return accuracy;
}
/**
* 上传文件重命名
* @return 新的文件名
*/
public static StringBuffer fileRename() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String time = sdf.format(new Date());
StringBuffer buf = new StringBuffer(time);
Random r = new Random();
//循环取得三个不大于10的随机整数
for (int x = 0; x < 3; x++) {
buf.append(r.nextInt(10));
}
return buf;
}
/**
* 对中文字符进行UTF-8编码
* @param source 要转义的字符串
* @return
* @throws UnsupportedEncodingException
*/
public static String transformStyle(String source) throws UnsupportedEncodingException
{
char[] arr = source.toCharArray();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < arr.length; i++)
{
char temp = arr[i];
if(isChinese(temp))
{
sb.append(URLEncoder.encode("" + temp, "UTF-8"));
continue;
}
sb.append(arr[i]);
}
return sb.toString();
}
/**
* 判断是不是中文字符
* @param c
* @return
*/
public static boolean isChinese(char c)
{
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if(ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS)
{
return true;
}
return false;
}
/**
* 判断指定的文件或文件夹删除是否成功
* @param FileName 文件或文件夹的路径
* @return true or false 成功返回true,失败返回false
*/
public static boolean deleteAnyone(String FileName){
File file = new File(FileName);//根据指定的文件名创建File对象
if ( !file.exists() ){ //要删除的文件不存在
System.out.println("文件"+FileName+"不存在,删除失败!" );
return false;
}else{ //要删除的文件存在
if ( file.isFile() ){ //如果目标文件是文件
return deleteFile(FileName);
}else{ //如果目标文件是目录
return deleteDir(FileName);
}
}
}
/**
* 判断指定的文件删除是否成功
* @param fileName 文件路径
* @return true or false 成功返回true,失败返回false
*/
public static boolean deleteFile(String fileName){
File file = new File(fileName);//根据指定的文件名创建File对象
if ( file.exists() && file.isFile() ){ //要删除的文件存在且是文件
if (file.delete()){
System.out.println("文件"+fileName+"删除成功!");
return true;
}else{
System.out.println("文件"+fileName+"删除失败!");
return false;
}
}else{
System.out.println("文件"+fileName+"不存在,删除失败!" );
return false;
}
}
/**
* 删除指定的目录以及目录下的所有子文件
* @param dirName is 目录路径
* @return true or false 成功返回true,失败返回false
*/
public static boolean deleteDir(String dirName){
if (dirName.endsWith(File.separator) )//dirName不以分隔符结尾则自动添加分隔符
dirName = dirName + File.separator;
File file = new File(dirName);//根据指定的文件名创建File对象
if ( !file.exists() || ( !file.isDirectory() ) ){ //目录不存在或者
System.out.println("目录删除失败"+dirName+"目录不存在!" );
return false;
}
File[] fileArrays = file.listFiles();//列出源文件下所有文件,包括子目录
for ( int i = 0 ; i < fileArrays.length ; i++ ){//将源文件下的所有文件逐个删除
deleteAnyone(fileArrays[i].getAbsolutePath());
}
if ( file.delete() ){
//删除当前目录
System.out.println("目录"+dirName+"删除成功!" );
}
return true;
}
}