实现阿里云OSS进行多文件压缩下载,压缩包中不同的文件可以自定义放在不同的文件夹下,每个文件名和压缩包名也可以自定义
工具类如下:
public class OssClientUtils { // 都是配置信息oss public static final String END_POINT = "oss-cn-beijing.aliyuncs.com"; private static final String ACCESS_KEY_ID = "sdfdsfsgg"; private static final String ACCESS_KEY_SECRET = "sdfsfsfdsg"; private static final OSSClient OSS_CLIENT; static { // 根据配置信息创建oss客户端对象 OSS_CLIENT = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET); } /** * 多文件自定义多级文件夹、文件名压缩下载 * @param zipName 压缩文件下载名,例如:压缩包名称.zip,需要带zip后缀 * @param bucketName * @param list 自定义内容,name:自定义下载的文件名;filePath:文件在oss存储的全路径,第一个/需要去掉 * dir:压缩包中文件目录路径,可以是多级目录,以/结束,不以/开头 * @param response * @return void */ public static void zipDownload(String zipName, String bucketName, List<Map<String, Object>> list, HttpServletResponse response){ // 设置强制下载不打开 response.setContentType("application/force-download"); ZipOutputStream zos = null; BufferedInputStream bis = null; BufferedOutputStream out = null; byte[] buffer = new byte[100 * 1024]; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { // 用于将数据压缩成Zip文件格式 zos = new ZipOutputStream(baos); for (int j = 0; j < list.size(); j++) { Map<String, Object> map = list.get(j); // 下载的自定义文件名(包含文件后缀) String name = (String) map.get("name"); /** * 文件oss的路径,去掉Bucket,不能以/开头; * 例如oss文件路径为:https://yigoutest.oss-cn-beijing.aliyuncs.com/food_safety/2021-01-04/1/cpu.jpg * 则map中为filePath:food_safety/2021-01-04/1/cpu.jpg */ String filePath = (String) map.get("filePath"); // 下载的自定义文件夹目录 String dir = (String) map.get("dir"); //bucketName需改为自己的bucketName OSSObject ossObject = OSS_CLIENT.getObject(bucketName, filePath); bis = new BufferedInputStream(ossObject.getObjectContent()); zos.putNextEntry(new ZipEntry(dir + name)); int i = bis.read(buffer); // 向压缩文件中输出数据 while(i != -1){ zos.write(buffer, 0, i); i = bis.read(buffer); } zos.closeEntry(); } // 设置文件名 response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(zipName , "UTF-8")); out=new BufferedOutputStream(response.getOutputStream()); out.write(baos.toByteArray()); } catch (Exception e) { e.printStackTrace(); } finally { //关闭流 if(zos != null){ try { zos.close(); } catch (IOException e) { e.printStackTrace(); } }if(bis != null){ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } if(out != null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
调用工具类demo如下:
/** * 参考:阿里云(oss)官网api地址 * https://help.aliyun.com/product/31815.html */ @RequestMapping(value = "/zipDownload") public void zipDownload(HttpServletResponse response){ List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map1 = new HashMap<>(); map1.put("dir", "test/"); map1.put("name","test.jpg"); map1.put("filePath", "food_safety/2021-01-04/1/cpu.jpg"); list.add(map1); Map<String, Object> map2 = new HashMap<>(); map2.put("dir", "test/哈哈/"); map2.put("name","哈哈.jpg"); map2.put("filePath", "food_safety/2021-01-04/1/cpu.jpg"); list.add(map2); Map<String, Object> map3 = new HashMap<>(); map3.put("dir", "啧啧/"); map3.put("name","啧啧.jpg"); map3.put("filePath", "food_safety/2021-01-04/1/cpu.jpg"); list.add(map3); Map<String, Object> map4 = new HashMap<>(); map4.put("dir", "啧啧/tt/ss/嗯嗯/"); map4.put("name","sfsd是搭嘎第三个.jpg"); map4.put("filePath", "food_safety/2021-01-04/1/cpu.jpg"); list.add(map4); // gunsProperties.getOssBucket() 得到的是文件存储位置的bucket OssClientUtils.zipDownload("压缩文件下载测试.zip", gunsProperties.getOssBucket(), list, response); }
这种方式工具类下载的压缩包,采用winrar打不开,别的压缩工具可以打开,所以修改工具类如下:
public class OssClientUtils { // 都是配置信息oss public static final String END_POINT = "oss-cn-beijing.aliyuncs.com"; private static final String ACCESS_KEY_ID = "sdfdsfsgg"; private static final String ACCESS_KEY_SECRET = "sdfsfsfdsg"; private static final OSSClient OSS_CLIENT; static { // 根据配置信息创建oss客户端对象 OSS_CLIENT = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET); } /** * 多文件自定义多级文件夹、文件名压缩下载 * @param zipName 压缩文件下载名,例如:压缩包名称.zip,需要带zip后缀 * @param bucketName * @param list 自定义内容,name:自定义下载的文件名;filePath:文件在oss存储的全路径,第一个/需要去掉 * dir:压缩包中文件目录路径,可以是多级目录,以/结束,不以/开头 * @param response * @return void */ public static void zipDownload(String zipName, String bucketName, List<Map<String, Object>> list, HttpServletResponse response){ response.setCharacterEncoding("utf-8"); response.setContentType("multipart/form-data"); BufferedInputStream bis = null; try { response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(zipName , "UTF-8")); ZipOutputStream zos = new ZipOutputStream(response.getOutputStream()); int sortNum = 0; for (int j = 0; j < list.size(); j++) { Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000); Map<String, Object> map = list.get(j); // 下载的自定义文件名(包含文件后缀) String name = (String) map.get("name"); /** * 文件oss的路径,去掉Bucket,不能以/开头; * 例如oss文件路径为:https://yigoutest.oss-cn-beijing.aliyuncs.com/food_safety/2021-01-04/1/cpu.jpg * 则map中为filePath:food_safety/2021-01-04/1/cpu.jpg */ String filePath = (String) map.get("filePath"); // 下载的自定义文件夹目录 String dir = (String) map.get("dir"); GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, filePath, HttpMethod.GET); // 设置过期时间。 request.setExpiration(expiration); // 生成签名URL(HTTP GET请求)。 URL signedUrl = OSS_CLIENT.generatePresignedUrl(request); // 使用签名URL发送请求。 OSSObject ossObject = OSS_CLIENT.getObject(signedUrl, new HashMap<>()); if (ossObject != null) { InputStream inputStream = ossObject.getObjectContent(); byte[] buffs = new byte[1024 * 10]; ZipEntry zipEntry = new ZipEntry(dir + name); zos.putNextEntry(zipEntry); bis = new BufferedInputStream(inputStream, 1024 * 10); int read; while ((read = bis.read(buffs, 0, 1024 * 10)) != -1) { zos.write(buffs, 0, read); } ossObject.close(); } sortNum++; } zos.close(); } catch (Exception e) { e.printStackTrace(); } finally { //关闭流 try { if (null != bis) { bis.close(); } response.getOutputStream().flush(); response.getOutputStream().close(); } catch (IOException e) { e.printStackTrace(); } } } }