Java工程师实现视频文件上传minio文件体系存储及网页实现分批加载视频播放

[复制链接]
发表于 2025-11-16 04:52:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Java工程师实现minio存储大型视频文件网页实现分批加载视频播放


一、需求分析

老板给我出个标题,让我把的影戏文件上传到minio文件体系,再通过WEB端分配加载视频播放,雷同于我们平常的影戏网站。小编把Java代码共享出来。是真正的能拿过来直接用的。小编我切身测过。
1.1minio版本

  1. <dependency>
  2.                     <groupId>io.minio</groupId>
  3.                     <artifactId>minio</artifactId>
  4.                     <version>7.1.4</version>
  5.                 </dependency>
复制代码
1.2maven依赖

  1. <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.sun</groupId>    <artifactId>springboot-sun</artifactId>    <version>1.0-SNAPSHOT</version>    <!--springboot工程必要继续的父工程-->    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.1.8.RELEASE</version>    </parent>    <dependencies>                <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-thymeleaf</artifactId>    </dependency>                    <!--web开辟的起步依赖-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.mybatis.spring.boot</groupId>            <artifactId>mybatis-spring-boot-starter</artifactId>            <version>2.1.0</version>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <!--<scope>runtime</scope>-->        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>                <dependency>
  2.                     <groupId>io.minio</groupId>
  3.                     <artifactId>minio</artifactId>
  4.                     <version>7.1.4</version>
  5.                 </dependency>
  6.                 <dependency>                    <groupId>org.apache.commons</groupId>                    <artifactId>commons-lang3</artifactId>                    <version>3.12.0</version>                </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>1.18.28</version>            <scope>provided</scope>        </dependency>        <dependency>    <groupId>joda-time</groupId>    <artifactId>joda-time</artifactId>    <version>2.10.12</version></dependency>    </dependencies></project>
复制代码
1.3分段视频播放Controller

  1. package com.sun.controller;
  2. import io.minio.GetObjectArgs;
  3. import io.minio.MinioClient;
  4. import io.minio.ObjectStat;
  5. import io.minio.StatObjectArgs;
  6. import io.minio.errors.*;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.http.HttpHeaders;
  9. import org.springframework.http.HttpStatus;
  10. import org.springframework.http.MediaType;
  11. import org.springframework.http.ResponseEntity;
  12. import org.springframework.web.bind.annotation.GetMapping;
  13. import org.springframework.web.bind.annotation.PathVariable;
  14. import org.springframework.web.bind.annotation.RequestHeader;
  15. import org.springframework.web.bind.annotation.RestController;
  16. import com.sun.minio.util.MinIoUtil;
  17. import java.io.ByteArrayOutputStream;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.security.InvalidKeyException;
  21. import java.security.NoSuchAlgorithmException;
  22. @RestController
  23. public class VideoController2 {
  24.     @GetMapping("/testDisplay2/{fileName}")
  25.     public ResponseEntity<byte[]> getVideo(
  26.             @PathVariable String fileName,
  27.             @RequestHeader(value = "Range", required = false) String range) {
  28.         try {
  29.                  String bucketName = "movie";
  30.              String objectName = fileName + ".mp4";
  31.              MinioClient minioClient= MinIoUtil.minioClient;
  32.             // 根据Range请求头来设置分批加载的范围
  33.             GetObjectArgs.Builder getObjectArgsBuilder = GetObjectArgs.builder()
  34.                  .bucket(bucketName)
  35.                  .object(objectName);
  36.             long start=0l;
  37.             if (range!= null && range.startsWith("bytes=")) {
  38.                 String[] values = range.split("=")[1].split("-");
  39.                  start = Long.parseLong(values[0]);
  40.                 long end = values.length > 1? Long.parseLong(values[1]) : -1;
  41.                 if (end!= -1) {
  42.                     long length = end - start + 1;
  43.                     getObjectArgsBuilder.offset(start).length(length);
  44.                 } else {
  45.                     getObjectArgsBuilder.offset(start);
  46.                 }
  47.             }
  48.             // 获取视频流
  49.             try (InputStream inputStream = minioClient.getObject(getObjectArgsBuilder.build())) {
  50.                 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  51.                 byte[] buffer = new byte[1024 * 1024]; // 1MB缓冲区
  52.                 int length;
  53.                 while ((length = inputStream.read(buffer))!= -1) {
  54.                     outputStream.write(buffer, 0, length);
  55.                 }
  56.                 byte[] videoBytes = outputStream.toByteArray();
  57.                 HttpHeaders headers = new HttpHeaders();
  58.                 headers.setContentType(MediaType.parseMediaType("video/mp4"));
  59.                 // 如果是分段请求,设置相应的响应头
  60.                 if (range!= null) {
  61.                     ObjectStat objectStat = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
  62.                     long fileSize = objectStat.length();
  63.                     headers.set("Content-Range", "bytes " + start + "-" + (start + videoBytes.length - 1) + "/" + fileSize);
  64.                     return new ResponseEntity<>(videoBytes, headers, HttpStatus.PARTIAL_CONTENT);
  65.                 } else {
  66.                     headers.setContentLength(videoBytes.length);
  67.                     return new ResponseEntity<>(videoBytes, headers, HttpStatus.OK);
  68.                 }
  69.             }
  70.         } catch (Exception e) {
  71.             e.printStackTrace();
  72.             return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
  73.         }
  74.     }
  75. }
复制代码
1.4 html5 播放

  1. <html>
  2. <title>test</title>
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  4. <head>
  5.     <style type="text/css">
  6.         .upload {
  7.             margin-top: 100px;
  8.             margin-left: 100px;
  9.             text-align: center;
  10.         }
  11.     </style>
  12. </head>
  13. <body>
  14. <h1 style="text-align: center;margin-top: 20px">test</h1>
  15. <div>
  16. <!--  <img src="/minio_demo/testClick/testDisplay?url=/data/temp/img/a6efce1b9d16fdfabf36882ab08f8c5495ee7b9f.jpg"> -->
  17. </div>
  18. <div>
  19.   <!--   
  20.    
  21. <video src="/minio_demo/testClick/testDisplay?md5=a172e15a869fd7224618840c0815dcb1" controls width="640" height="360">
  22.     您的浏览器不支持视频标签。
  23. </video>
  24.    -->
  25.    
  26.     <video src="/minio_demo/testDisplay2/test" controls width="640" height="360">
  27.     您的浏览器不支持视频标签。
  28. </video>
  29.    
  30.    
  31. </div>
  32. </body>
  33. </html>
复制代码
1.5上传Controller

  1. package com.sun.controller;
  2. import io.minio.errors.*;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.core.io.support.PropertiesLoaderUtils;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestParam;
  8. import org.springframework.web.bind.annotation.ResponseBody;
  9. import org.springframework.web.bind.annotation.RestController;
  10. import org.springframework.web.multipart.MultipartFile;
  11. import org.springframework.web.servlet.ModelAndView;
  12. import com.sun.minio.util.MinIoContentType;
  13. import com.sun.minio.util.MinIoUtil;
  14. import com.sun.minio.util.MinioBucketEnum;
  15. import com.sun.service.MinioServiceImpl;
  16. import javax.servlet.RequestDispatcher;
  17. import javax.servlet.ServletException;
  18. import javax.servlet.http.HttpServletRequest;
  19. import javax.servlet.http.HttpServletResponse;
  20. import java.io.IOException;
  21. import java.io.InputStream;
  22. import java.security.InvalidKeyException;
  23. import java.security.NoSuchAlgorithmException;
  24. import java.util.Properties;
  25. @RestController
  26. @RequestMapping("testClick")
  27. public class MinioDemoController {
  28.          @Autowired
  29.         private MinioServiceImpl minioServiceImpl;
  30.     /**
  31.      * 直接页面展示
  32.      * @param response
  33.      */
  34.     @RequestMapping("/testDisplay")
  35.     public void testDisplay(HttpServletResponse response,String md5) throws Exception {
  36.         MinIoUtil.displayFile(minioServiceImpl,MinioBucketEnum.VIDEO_FILES,response,md5);
  37.     }
  38.     @RequestMapping("/testDownload")
  39.     public void testDownLoad(HttpServletResponse response,String md5) throws Exception {
  40.         MinIoUtil.downloadFile(minioServiceImpl,MinioBucketEnum.VIDEO_FILES,response,md5,"");
  41.     }
  42.     @RequestMapping("/testLoad")
  43.     public void testLoadFile(HttpServletResponse response,String md5,String targetPath) throws  Exception{
  44.         MinIoUtil.loadObject(MinioBucketEnum.VIDEO_FILES,targetPath,md5);
  45.     }
  46.     @RequestMapping("/deleteFile")
  47.     public String deleteFile(String md5) throws  Exception{
  48.         MinIoUtil.deleteObject(minioServiceImpl,MinioBucketEnum.VIDEO_FILES, md5);
  49.         return "deleteFileSucceed";
  50.     }
  51.    
  52.    
  53.     @RequestMapping("/testUpload")
  54.     @ResponseBody
  55.     public String testUpload(HttpServletRequest request, @RequestParam("multipartFile") MultipartFile[] multipartfiles,String url,String pucketName)throws  Exception{
  56.         String filePath = "";
  57.         for(MultipartFile multipartFile:multipartfiles){
  58.             String contentType = multipartFile.getContentType();
  59.             InputStream inputStream = multipartFile.getInputStream();
  60.             if(!StringUtils.isBlank(url)&&!url.startsWith("/")){
  61.                 url = "/"+url;
  62.             }
  63.             if(!StringUtils.isBlank(url)&&!url.endsWith("/")){
  64.                 url += "/";
  65.             }
  66.             MinioBucketEnum minioBucketEnum = MinioBucketEnum.VIDEO_FILES;
  67.                         /*
  68.                          * if(pucketName.equals("monthlytext")){ minioBucketEnum =
  69.                          * MinioBucketEnum.MONTHLY_TEXT; } if(pucketName.equals("email")){
  70.                          * minioBucketEnum = MinioBucketEnum.VIDEO_FILES; }
  71.                          * if(pucketName.equals("excel")){ minioBucketEnum = MinioBucketEnum.EXCEL; }
  72.                          */
  73.             
  74.             String md5 = MinIoUtil.upload(minioServiceImpl,minioBucketEnum,url + multipartFile.getOriginalFilename(), inputStream, MinIoContentType.getContentType(contentType));
  75.             filePath+="<p>"+md5+"</p>";
  76.             if(multipartFile.getOriginalFilename().contains(".mp4")) {
  77.                 filePath = "<video src="/minio_demo/testClick/testDisplay?md5="+md5+"" controls width="640" height="360">\n" +
  78.                         "    您的浏览器不支持视频标签。\n" +
  79.                         "</video>";
  80.             }
  81.             // 构建包含两个a标签的HTML代码字符串
  82.             StringBuilder htmlBuilder = new StringBuilder();
  83.             htmlBuilder.append("<a href="/minio_demo/testClick/deleteFile?md5=").append(md5).append("">删除文件</a>");
  84.             htmlBuilder.append("&nbsp;&nbsp;&nbsp;&nbsp;"); // 增加一些空格间隔两个标签
  85.             htmlBuilder.append("<a href="/minio_demo/testClick/testDownload?md5=").append(md5).append("">下载文件</a>");
  86.             // 得到最终的HTML字符串
  87.             String htmlString = htmlBuilder.toString();
  88.             filePath=filePath+htmlString;
  89.            // filePath+="<p>"+md5+"</p>";
  90.         }
  91.         return filePath;
  92.     }
  93.     @RequestMapping("/testMv1")
  94.     public ModelAndView testMv1(HttpServletRequest request){
  95.         ModelAndView modelAndView = new ModelAndView();
  96.         modelAndView.setViewName("/minio/demo");
  97.         return modelAndView;
  98.     }
  99.     @RequestMapping("/testMv2")
  100.     public ModelAndView testMv2(HttpServletRequest request){
  101.         ModelAndView modelAndView = new ModelAndView();
  102.         modelAndView.setViewName("/minio/demo2");
  103.         return modelAndView;
  104.     }
  105.     @RequestMapping("/testMv3")
  106.     public ModelAndView testMv3(){
  107.         ModelAndView mv = new ModelAndView();
  108.         mv.setViewName("/minio/demo3");
  109.         return mv;
  110.     }
  111. }
复制代码
1.6 上传HTML5

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <title>文件上传页面</title>
  5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  6.     <style type="text/css">
  7.         /* 整体页面样式 */
  8.         body {
  9.             font-family: Arial, sans-serif;
  10.             margin: 0;
  11.             padding: 0;
  12.             display: flex;
  13.             flex-direction: column;
  14.             justify-content: center;
  15.             align-items: center;
  16.             min-height: 100vh;
  17.             background-color: #f4f4f4;
  18.         }
  19.         /* 标题样式 */
  20.         h1 {
  21.             color: #333;
  22.             margin-bottom: 30px;
  23.         }
  24.         /* 上传表单容器样式 */
  25.       .upload {
  26.             background-color: #fff;
  27.             padding: 30px;
  28.             border-radius: 10px;
  29.             box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  30.             width: 400px;
  31.         }
  32.         /* 表单段落样式 */
  33.       .upload p {
  34.             margin-bottom: 20px;
  35.         }
  36.         /* 文件选择输入框样式 */
  37.       .upload input[type="file"] {
  38.             width: 100%;
  39.             padding: 10px;
  40.             border: 1px solid #ccc;
  41.             border-radius: 5px;
  42.         }
  43.         /* 文本输入框样式 */
  44.       .upload input[type="text"] {
  45.             width: 100%;
  46.             padding: 10px;
  47.             border: 1px solid #ccc;
  48.             border-radius: 5px;
  49.         }
  50.         /* 提交按钮样式 */
  51.       .upload input[type="submit"] {
  52.             background-color: #007BFF;
  53.             color: #fff;
  54.             padding: 10px 20px;
  55.             border: none;
  56.             border-radius: 5px;
  57.             cursor: pointer;
  58.             transition: background-color 0.3s ease;
  59.         }
  60.       .upload input[type="submit"]:hover {
  61.             background-color: #0056b3;
  62.         }
  63.     </style>
  64. </head>
  65. <body>
  66.     <h1>文件上传至MinIO</h1>
  67.     <div class="upload">
  68.         <form action="/minio_demo/testClick/testUpload" method="post" enctype="multipart/form-data">
  69.             <p>
  70.                 选择文件: <input type="file" name="multipartFile" />
  71.             </p>
  72.             <p>
  73.                 桶名称: <input type="text" name="pucketName" value="movie" />
  74.             </p>
  75.             <p>
  76.                 文件目录: <input type="text" name="url" hidden />
  77.             </p>
  78.             <p>
  79.                 <input type="submit" value="上传并检测" />
  80.             </p>
  81.         </form>
  82.     </div>
  83. </body>
  84. </html>
复制代码

1.7 MinIoUtil工具类

  1. package com.sun.minio.util;
  2. import io.minio.*;
  3. import io.minio.errors.*;
  4. import org.apache.commons.lang3.StringUtils;
  5. import org.joda.time.DateTime;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.beans.BeansException;
  8. import org.springframework.context.ApplicationContext;
  9. import org.springframework.context.ApplicationContextAware;
  10. import org.springframework.core.io.support.PropertiesLoaderUtils;
  11. import org.springframework.web.multipart.MultipartFile;
  12. import com.sun.doman.MinioRecord;
  13. import com.sun.service.MinioServiceImpl;
  14. import javax.servlet.ServletOutputStream;
  15. import javax.servlet.http.HttpServletResponse;
  16. import javax.validation.constraints.NotNull;
  17. import java.io.*;
  18. import java.net.URLEncoder;
  19. import java.security.InvalidKeyException;
  20. import java.security.NoSuchAlgorithmException;
  21. import java.util.HashMap;
  22. import java.util.Map;
  23. import java.util.Properties;
  24. import java.util.concurrent.TimeUnit;
  25. /**
  26. * minio工具类
  27. */
  28. /**
  29. * minio工具类
  30. */
  31. public class MinIoUtil {
  32.     private static MinioServiceImpl minioService = null;
  33.     private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(MinIoUtil.class);
  34.     public static MinioClient minioClient = null;
  35.     private static  String enpoint;
  36.     private static  String username;
  37.     private static  String password;
  38.     static {
  39.         try{
  40.             Properties properties = PropertiesLoaderUtils.loadAllProperties("application.properties");
  41.             enpoint = properties.getProperty("minioEnpoint");
  42.             Logger.info("获取minio[enpoint]:"+enpoint);
  43.             username = properties.getProperty("minioUserName");
  44.             Logger.info("获取minio[minioUserName]:"+username);
  45.             password = properties.getProperty("minioPassword");
  46.             Logger.info("获取minio[minioPassword]"+password);
  47.             minioClient = MinioClient.builder().endpoint(enpoint).credentials(username,password).build();
  48.             for(MinioBucketEnum minioBucketEnum: MinioBucketEnum.values()){
  49.                 if(!bucketExist(minioBucketEnum.getBucketName())){
  50.                     createBucket(minioBucketEnum.getBucketName());
  51.                 }
  52.             }
  53.         }catch (Exception e){
  54.             Logger.error("获取minio连接失败",e);
  55.             e.printStackTrace();
  56.         }
  57.     }
  58.    
  59.    
  60.    
  61.    
  62.   
  63.    
  64.    
  65.    
  66.     //检查桶是否存在
  67.     public static boolean bucketExist(String buckeyName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {
  68.         return minioClient.bucketExists(BucketExistsArgs.builder().bucket(buckeyName).build());
  69.     }
  70.     //创建桶
  71.     public static  void createBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, RegionConflictException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {
  72.         minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
  73.     }
  74.     /**
  75.      *
  76.      * @return
  77.      */
  78.     public Map<String,String> getAccess(){
  79.         Map<String,String> map = new HashMap<>();
  80.         map.put("username",username);
  81.         map.put("password",password);
  82.         return map;
  83.     }
  84.     /**
  85.      *
  86.      * @param name 文件名,可以是单纯的文件名test.pdf,也可以是类似aaa/bbb/ccc/test.pdf,如果没有重复文件名,则会为在minio中的文件路径
  87.      * @param inputStream 文件流
  88.      * @param contentType
  89.      * @return
  90.      */
  91.     public static String upload(MinioServiceImpl minioService ,MinioBucketEnum minioBucketEnum, String name, InputStream inputStream, MinIoContentType contentType)throws Exception{
  92.         if(StringUtils.isBlank(name)||inputStream==null){
  93.             return null;
  94.         }
  95.         try{
  96.             BufferedInputStream bis = new BufferedInputStream(inputStream);
  97.             String md5Val = MD5Util.md5HashCode32(bis);
  98.             MinioRecord byMd5Val = minioService.getByMd5Val(minioBucketEnum.getBucketName(),md5Val);
  99.             if(byMd5Val==null){
  100.                 if(objectExist(minioBucketEnum.getBucketName(),name)){//minio存在同名文件,需要改一下文件名
  101.                     name = getOtherName(name,md5Val);
  102.                 }
  103.                 boolean flag = false;
  104.                 int count = 3;
  105.                 for(int i = 0;i<count;i++){//失败尝试3次.最后一次还失败抛异常
  106.                     if(flag){
  107.                         break;
  108.                     }
  109.                     try{
  110.                         minioClient.putObject(PutObjectArgs.builder().bucket(minioBucketEnum.getBucketName()).object(name).contentType(contentType == null ? MinIoContentType.STREAM.contentType : contentType.contentType)
  111.                                 .stream(bis, bis.available(), partSize).build());
  112.                         flag = true;
  113.                     }catch (Exception e){
  114.                         if (i==count-1){
  115.                             throw e;
  116.                         }
  117.                         TimeUnit.MILLISECONDS.sleep(200);
  118.                     }
  119.                 }
  120.                 minioService.insertOne(MinioRecord.builder().bucketName(minioBucketEnum.getBucketName()).md5Val(md5Val).minioFilePath(name).remainNum(1)
  121.                         .createTime(DateTime.now().toString("yyyy-MM-dd HH:mm:ss")).updateTime(DateTime.now().toString("yyyy-MM-dd HH:mm:ss")).build());
  122.             }else{
  123.                 byMd5Val.setRemainNum((byMd5Val.getRemainNum()==null?0:byMd5Val.getRemainNum())+1);
  124.                 minioService.updateRemainNum(byMd5Val);
  125.             }
  126.             return md5Val;
  127.         }catch (Exception e){
  128.             Logger.error("上传文件失败,name:"+name,e);
  129.             throw e;
  130.         }finally {
  131.             try{
  132.                 inputStream.close();
  133.             }catch (Exception e){
  134.             }
  135.         }
  136.     }
  137.    
  138.    
  139.    
  140.    
  141.    
  142.    
  143.     public static String upload(MinioBucketEnum minioBucketEnum, String name, InputStream inputStream, MinIoContentType contentType)throws Exception{
  144.         if(StringUtils.isBlank(name)||inputStream==null){
  145.             return null;
  146.         }
  147.         try{
  148.             BufferedInputStream bis = new BufferedInputStream(inputStream);
  149.             String md5Val = MD5Util.md5HashCode32(bis);
  150.             MinioRecord byMd5Val = minioService.getByMd5Val(minioBucketEnum.getBucketName(),md5Val);
  151.             if(byMd5Val==null){
  152.                 if(objectExist(minioBucketEnum.getBucketName(),name)){//minio存在同名文件,需要改一下文件名
  153.                     name = getOtherName(name,md5Val);
  154.                 }
  155.                 boolean flag = false;
  156.                 int count = 3;
  157.                 for(int i = 0;i<count;i++){//失败尝试3次.最后一次还失败抛异常
  158.                     if(flag){
  159.                         break;
  160.                     }
  161.                     try{
  162.                         minioClient.putObject(PutObjectArgs.builder().bucket(minioBucketEnum.getBucketName()).object(name).contentType(contentType == null ? MinIoContentType.STREAM.contentType : contentType.contentType)
  163.                                 .stream(bis, bis.available(), partSize).build());
  164.                         flag = true;
  165.                     }catch (Exception e){
  166.                         if (i==count-1){
  167.                             throw e;
  168.                         }
  169.                         TimeUnit.MILLISECONDS.sleep(200);
  170.                     }
  171.                 }
  172.                 minioService.insertOne(MinioRecord.builder().bucketName(minioBucketEnum.getBucketName()).md5Val(md5Val).minioFilePath(name).remainNum(1)
  173.                         .createTime(DateTime.now().toString("yyyy-MM-dd HH:mm:ss")).updateTime(DateTime.now().toString("yyyy-MM-dd HH:mm:ss")).build());
  174.             }else{
  175.                 byMd5Val.setRemainNum((byMd5Val.getRemainNum()==null?0:byMd5Val.getRemainNum())+1);
  176.                 minioService.updateRemainNum(byMd5Val);
  177.             }
  178.             return md5Val;
  179.         }catch (Exception e){
  180.             Logger.error("上传文件失败,name:"+name,e);
  181.             throw e;
  182.         }finally {
  183.             try{
  184.                 inputStream.close();
  185.             }catch (Exception e){
  186.             }
  187.         }
  188.     }
  189.    
  190.    
  191.    
  192.    
  193.    
  194.    
  195.    
  196.    
  197.    
  198.    
  199.    
  200.    
  201.    
  202.    
  203.    
  204.    
  205.    
  206.    
  207.    
  208.    
  209.     /**
  210.      *
  211.      * @param name 文件名,可以是单纯的文件名test.pdf,也可以是类似aaa/bbb/ccc/test.pdf,如果没有重复文件名,则会为在minio中的文件路径
  212.      * @param filePath 需要上传的文件路径
  213.      * @param contentType
  214.      * @return
  215.      */
  216.     public static String upload(MinioBucketEnum minioBucketEnum, String name, String filePath, MinIoContentType contentType) throws Exception {
  217.         File file = new File(filePath);
  218.         if(!file.exists()||minioBucketEnum==null){
  219.             return null;
  220.         }
  221.         return upload(minioBucketEnum,name, new FileInputStream(file), contentType);
  222.     }
  223.     /**
  224.      * 基于MultipartFile文件上传
  225.      * @param minioBucketEnum 桶信息
  226.      * @param file 文件
  227.      * @param contentType 内容类型
  228.      * @return 返回结果
  229.      * @throws Exception 异常
  230.      */
  231.     public static String upload(@NotNull MinioBucketEnum minioBucketEnum, @NotNull MultipartFile file, MinIoContentType contentType) throws Exception {
  232.         String filename = file.getOriginalFilename();
  233.         byte[] bytes = file.getBytes();
  234.         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
  235.         String md5Str = upload(minioBucketEnum, filename, bais, contentType);
  236.         bais.close();
  237.         return md5Str;
  238.     }
  239.     /**
  240.      *
  241.      * @param response
  242.      * @param md5ValOrOldPath 新文件上传则是md5值,旧文件则依然使用旧文件的路径
  243.      * @param exportFileName 最终给到前端的文件名
  244.      */
  245.     public static void downloadFile(MinioServiceImpl minioService ,MinioBucketEnum minioBucketEnum, HttpServletResponse response, String md5ValOrOldPath,String exportFileName){
  246.         downloadFileByMd5(minioService,minioBucketEnum,response,checkOutMd5Val(md5ValOrOldPath),exportFileName);
  247.     }
  248.     /**
  249.      * 根据文件md5值获取
  250.      * @param md5Val
  251.      * @return
  252.      */
  253.     private static void downloadFileByMd5(MinioServiceImpl minioService ,MinioBucketEnum minioBucketEnum, HttpServletResponse response, String md5Val,String exportFileName){
  254.         if(StringUtils.isBlank(md5Val)||response==null){
  255.             return ;
  256.         }
  257.         try {
  258.             MinioRecord byMd5Val = minioService.getByMd5Val(minioBucketEnum.getBucketName(),md5Val);
  259.             if(byMd5Val!=null){
  260.                 ObjectStat objectStat = minioClient.statObject(StatObjectArgs.builder().bucket(minioBucketEnum.getBucketName()).object(byMd5Val.getMinioFilePath()).build());
  261.                 DownloadUtils.downloadFile(response, minioClient.getObject(GetObjectArgs.builder().bucket(minioBucketEnum.getBucketName()).object(byMd5Val.getMinioFilePath()).build())
  262.                         , objectStat.name(), objectStat.length(), objectStat.contentType(), true, -1,exportFileName);
  263.             }
  264.         } catch (Exception e) {
  265.             Logger.error("下载文件失败",e);
  266.             e.printStackTrace();
  267.         }
  268.     }
  269.     /**
  270.      *
  271.      * @param response
  272.      * @param md5ValOrOldPath 新文件上传则是md5值,旧文件则依然使用旧文件的路径,最终都是通过文件md5找文件
  273.      * @throws Exception
  274.      */
  275.     public static void displayFile(MinioServiceImpl minioService ,MinioBucketEnum minioBucketEnum, HttpServletResponse response, String md5ValOrOldPath) throws Exception {
  276.         displayFileByMd5( minioService ,minioBucketEnum,response,checkOutMd5Val(md5ValOrOldPath));
  277.     }
  278.     /**
  279.      * 根据MD5值展示文件
  280.      * @param response
  281.      * @param md5Val
  282.      */
  283.     private static void displayFileByMd5(MinioServiceImpl minioService ,MinioBucketEnum minioBucketEnum, HttpServletResponse response, String md5Val) throws Exception {
  284.         MinioRecord byMd5Val = minioService.getByMd5Val(minioBucketEnum.getBucketName(),md5Val);
  285.         ObjectStat objectStat = minioClient.statObject(StatObjectArgs.builder().bucket(minioBucketEnum.getBucketName()).object(byMd5Val.getMinioFilePath()).build());
  286.         String objectName = objectStat.name();
  287.         String fileName = objectName.substring(objectName.lastIndexOf("/")+1);
  288.         response.setCharacterEncoding("utf-8");
  289.         response.setHeader("Content-Type",objectStat.contentType());
  290.         response.addHeader("Content-Disposition","inline;filename=" +  URLEncoder.encode(fileName, "UTF-8"));
  291.         response.addHeader("Content-Length","" + objectStat.length());
  292.         try(
  293.                 ServletOutputStream outputStream = response.getOutputStream();
  294.                 BufferedInputStream bufferedInputStream = new BufferedInputStream(getObjectInputStream(minioBucketEnum.getBucketName(),objectName));
  295.                 BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
  296.         ){
  297.             int lenth;
  298.             byte[] bytes = new byte[1024];
  299.             while ((lenth=bufferedInputStream.read(bytes,0,bytes.length))!=-1){
  300.                 bufferedOutputStream.write(bytes,0,lenth);
  301.             }
  302.             bufferedOutputStream.flush();
  303.         }catch (Exception e){
  304.             Logger.error("下载失败objectname:"+objectName,e);
  305.         }
  306.     }
  307.     /**
  308.      *
  309.      * @param name
  310.      * @param md5Val
  311.      * @return
  312.      */
  313.     private static String getOtherName(String name,String md5Val){
  314.         try{
  315.             String preFix = name.substring(0,name.lastIndexOf("/")+1);
  316.             if(!name.contains(".")){
  317.                 return preFix+md5Val;
  318.             }
  319.             String suffix = name.substring(name.lastIndexOf("."));
  320.             return preFix+md5Val+suffix;
  321.         }catch (Exception e){
  322.             //最起码把md5的值返回作为文件名
  323.             return md5Val;
  324.         }
  325.     }
  326.     /**
  327.      * 文件下载,可以下载到本地某个地址
  328.      * @param targetFilaPath 目标文件
  329.      * @param md5ValOrOldPath 要下载到的目标文件地址,文件如果已经存在就无法下载
  330.      * @throws Exception
  331.      */
  332.     public static void loadObject(MinioBucketEnum minioBucketEnum, String targetFilaPath, String md5ValOrOldPath) throws Exception{
  333.         loadOBbjectByMD5(minioBucketEnum,targetFilaPath,checkOutMd5Val(md5ValOrOldPath));
  334.     }
  335.     /**
  336.      * 文件下载,可以下载到本地某个地址
  337.      * @param targetFilePath 要下载到的目标文件地址,文件如果已经存在就无法下载
  338.      * @throws Exception
  339.      */
  340.     private static void loadOBbjectByMD5(MinioBucketEnum minioBucketEnum, String targetFilePath, String md5Val) throws Exception {
  341.         if(StringUtils.isBlank(targetFilePath)){
  342.             return ;
  343.         }
  344.         MinioRecord byMd5Val = minioService.getByMd5Val(minioBucketEnum.getBucketName(),md5Val);
  345.         if(byMd5Val==null){
  346.             return ;
  347.         }
  348.         File file = new File(targetFilePath);
  349.         if(file.exists()){
  350.             return ;
  351.         }
  352.         file.createNewFile();
  353.         loadOBbjectByMD5(minioBucketEnum,new FileOutputStream(file),md5Val);
  354.     }
  355.     /**
  356.      *
  357.      * @param os
  358.      * @param md5ValOrOldPath 新文件上传则是md5值,旧文件则依然使用旧文件的路径,最终都是通过文件md5找文件
  359.      * @throws Exception
  360.      */
  361.     public static void loadObject(MinioBucketEnum minioBucketEnum, OutputStream os, String md5ValOrOldPath) throws Exception{
  362.         //先判断是不是32位的md5值
  363.         loadOBbjectByMD5(minioBucketEnum,os,checkOutMd5Val(md5ValOrOldPath));
  364.     }
  365.     /**
  366.      * 看下传入参数是否是md5值,为md5值则直接返回..如果是旧文件系统保留的文件路径,需要看下迁移的文件中是否有过该文件,有则返回该文件的实际md5值
  367.      * 虽然可能会查两次数据库,不过问题不大,这表数据并不大
  368.      * @param md5ValOrOldPath
  369.      * @return
  370.      */
  371.     private static String checkOutMd5Val(String md5ValOrOldPath){
  372.         //先判断是不是32位的md5值
  373.         if(StringUtils.isBlank(md5ValOrOldPath)){
  374.             return "";
  375.         }
  376.         if(md5ValOrOldPath.length()!=32||md5ValOrOldPath.contains(".")||md5ValOrOldPath.contains("/")||md5ValOrOldPath.contains("\")){
  377.             String code = MD5Util.md5HashCode32Str(md5ValOrOldPath);
  378.             MinioRecord byOldPath = minioService.getByOldPathMD5(code);
  379.             if(byOldPath==null){
  380.                 return "";
  381.             }
  382.             md5ValOrOldPath = byOldPath.getMd5Val();
  383.         }
  384.         return md5ValOrOldPath;
  385.     }
  386.     /**
  387.      * 文件下载
  388.      * @param os 目标输出流
  389.      * @throws Exception
  390.      */
  391.     private static boolean loadOBbjectByMD5(MinioBucketEnum minioBucketEnum, OutputStream os, String md5Val)throws Exception{
  392.         if(StringUtils.isBlank(md5Val)||os==null){
  393.             return false;
  394.         }
  395.         MinioRecord byMd5Val = minioService.getByMd5Val(minioBucketEnum.getBucketName(),md5Val);
  396.         if(byMd5Val==null){
  397.             return false;
  398.         }
  399.         try(
  400.                 BufferedInputStream bufferedInputStream = new BufferedInputStream(getObjectInputStream(minioBucketEnum.getBucketName(),byMd5Val.getMinioFilePath()));
  401.                 BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(os);
  402.         ){
  403.             int lenth;
  404.             byte[] bytes = new byte[1024];
  405.             while ((lenth=bufferedInputStream.read(bytes,0,bytes.length))!=-1){
  406.                 bufferedOutputStream.write(bytes,0,lenth);
  407.             }
  408.             bufferedOutputStream.flush();
  409.             return true;
  410.         }catch (Exception e){
  411.             Logger.error("下载失败objname:"+byMd5Val.getMinioFilePath(),e);
  412.             throw e;
  413.         }
  414.     }
  415.     /**
  416.      * true存在
  417.      * @param bucketName
  418.      * @param name
  419.      * @return
  420.      */
  421.     private static boolean objectExist(String bucketName,String name)throws Exception{
  422.         try{
  423.             ObjectStat objectStat = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(name).build());
  424.             if(!StringUtils.isBlank(objectStat.name())){
  425.                 return true;
  426.             }
  427.             return false;
  428.         }catch (Exception e){
  429.             return false;
  430.         }
  431.     }
  432.     private static final long partSize = 1024*1024*5l;
  433.     /**
  434.      * 覆盖并上传文件
  435.      * @param bucketName
  436.      * @param name
  437.      * @param inputStream
  438.      * @throws Exception
  439.      */
  440.     /**
  441.      * 获取对象流
  442.      * @param bucketName
  443.      * @param objectName
  444.      * @return
  445.      */
  446.     private static InputStream getObjectInputStream(String bucketName,String objectName) throws Exception{
  447.         int count = 3;
  448.         for(int i = 0;i<count;i++){
  449.             try{
  450.                 InputStream object = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
  451.                 return object;
  452.             }catch (Exception e2){
  453.                 if(i==count-1){
  454.                     throw e2;
  455.                 }
  456.                 TimeUnit.MILLISECONDS.sleep(200);
  457.             }
  458.         }
  459.         return null;
  460.     }
  461.     /**
  462.      * 获取对象流
  463.      * @param bucketName
  464.      * @param objectName
  465.      * @return
  466.      */
  467.     public static InputStream getObjectInputStreamByMd5Val(String bucketName,String objectName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {
  468.         MinioRecord byMd5Val = minioService.getByMd5Val(bucketName, objectName);
  469.         InputStream object = null;
  470.         try {
  471.             object = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(byMd5Val.getMinioFilePath()).build());
  472.         } catch (Exception e) {
  473.             e.printStackTrace();
  474.             object = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(byMd5Val.getMinioFilePath()).build());
  475.         }
  476.         return object;
  477.     }
  478.     /**
  479.      * 根据md5值删除
  480.      * 新文件上传则是md5值,旧文件则依然使用旧文件的路径,最终都是通过文件md5找文件
  481.      * @return
  482.      */
  483.     public static void deleteObject(MinioServiceImpl minioService,MinioBucketEnum minioBucketEnum, String md5ValOrOldPath) throws Exception{
  484.         String md5Val = checkOutMd5Val(md5ValOrOldPath);
  485.         MinioRecord byMd5Val = minioService.getByMd5Val(minioBucketEnum.getBucketName(),md5Val);
  486.         if(byMd5Val==null){
  487.             return;
  488.         }
  489.         if(byMd5Val.getRemainNum()!=null&&byMd5Val.getRemainNum()<=1){
  490.             if(objectExist(minioBucketEnum.getBucketName(),byMd5Val.getMinioFilePath())){
  491.                 minioClient.removeObject(RemoveObjectArgs.builder().bucket(minioBucketEnum.getBucketName()).object(byMd5Val.getMinioFilePath()).build());
  492.                 minioService.deleteRecord(minioBucketEnum.getBucketName(),md5Val);
  493.             }
  494.         }else{
  495.             Integer remainNum = byMd5Val.getRemainNum();
  496.             if(remainNum==null){
  497.                 byMd5Val.setRemainNum(1);
  498.             }else{
  499.                 byMd5Val.setRemainNum(remainNum-1);
  500.             }
  501.             minioService.updateRemainNum(byMd5Val);
  502.         }
  503.     }
  504.     /**
  505.      * 仅供判断该文件是否存在.
  506.      * @param minioMd5Value
  507.      * @return
  508.      */
  509.     public static boolean isExist(MinioBucketEnum minioBucketEnum, String minioMd5Value) {
  510.         MinioRecord byMd5Val = minioService.getByMd5Val(minioBucketEnum.getBucketName(),minioMd5Value);
  511.         if(byMd5Val==null){
  512.             return false;
  513.         }else{
  514.             return true;
  515.         }
  516.     }
  517.     /**
  518.      * 返回minio数据库表的记录
  519.      * @return
  520.      */
  521.     public static MinioRecord getMinioRecordByMd5Value(MinioBucketEnum minioBucketEnum, String minioMd5Value){
  522.         return minioService.getByMd5Val(minioBucketEnum.getBucketName(),minioMd5Value);
  523.     }
  524.        
  525. }
复制代码
  1. package com.sun.minio.util;
  2. import org.apache.commons.lang3.StringUtils;
  3. public enum MinIoContentType {
  4.     PDF("application/pdf"),
  5.     STREAM("application/octet-stream"),
  6.     IMAGE("image/jpeg"),
  7.     VEDIO("video/mp4"),
  8.     TEXT("text/html")
  9.     ;
  10.     public String contentType;
  11.     private MinIoContentType(String contentType){
  12.         this.contentType = contentType;
  13.     }
  14.     public static MinIoContentType getContentType(String contentType){
  15.         for(MinIoContentType minIoContentType : MinIoContentType.values()){
  16.             if(minIoContentType.contentType.equals(contentType)){
  17.                 return minIoContentType;
  18.             }
  19.         }
  20.         return STREAM;
  21.     }
  22.     public static MinIoContentType getContentTypeByFileName(String fileName){
  23.         if(StringUtils.isBlank(fileName)){
  24.             return STREAM;
  25.         }
  26.         String substring = fileName.substring(fileName.lastIndexOf("."), fileName.length());
  27.         if(StringUtils.isBlank(substring)){
  28.             return STREAM;
  29.         }
  30.         substring = substring.toLowerCase();
  31.         if("pdf".equals(substring)){
  32.             return PDF;
  33.         }
  34.         if("png".equals(substring)||"jpg".equals(substring)||"jpng".equals(substring)||"gif".equals(substring)){
  35.             return IMAGE;
  36.         }
  37.         if("mp4".equals(substring)||"avi".equals(substring)||"mkv".equals(substring)||"mov".equals(substring)||"rmvb".equals(substring)
  38.                 ||"FLV".equals(substring)||"rmvb".equals(substring)||"rm".equals(substring)){
  39.             return VEDIO;
  40.         }
  41.         if("txt".equals(substring)){
  42.             return TEXT;
  43.         }
  44.         return STREAM;
  45.     }
  46. }
复制代码
  1. package com.sun.minio.util;
  2. public enum MinioBucketEnum {
  3.     //EMAIL("email"),
  4.     //EXCEL("excel"),
  5.     //TYPICAL("typical"),
  6.     //FIRE_CONTROL("firecontrol"),
  7.     //MONTHLY_TEXT("monthlytext");
  8.        
  9.         VIDEO_FILES("movie");
  10.        
  11.        
  12.     private String bucketName;
  13.     private MinioBucketEnum(String bucketName){
  14.         this.bucketName = bucketName;
  15.     }
  16.     public String getBucketName(){
  17.         return bucketName;
  18.     }
  19. }
复制代码
  1. package com.sun.minio.util;
  2. import java.io.BufferedInputStream;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.InputStream;
  6. import java.security.MessageDigest;
  7. /**
  8. * 网上copy的代码,获取文件的32位MD5值
  9. */
  10. public class MD5Util {
  11.     /**
  12.      * 保证文件的MD5值为32位
  13.      * @param filePath        文件路径
  14.      * @return
  15.      * @throws FileNotFoundException
  16.      */
  17.     public static String md5HashCode32(String filePath) throws Exception{
  18.         BufferedInputStream bfis = new BufferedInputStream(new FileInputStream(filePath));
  19.         return md5HashCode32(bfis);
  20.     }
  21.     /**
  22.      * java计算文件32位md5值
  23.      * @param fis 输入流
  24.      * @return
  25.      */
  26.     public static String md5HashCode32(InputStream fis) {
  27.         try {
  28.             fis.mark(Integer.MAX_VALUE);
  29.             //拿到一个MD5转换器,如果想使用SHA-1或SHA-256,则传入SHA-1,SHA-256
  30.             MessageDigest md = MessageDigest.getInstance("MD5");
  31.             //分多次将一个文件读入,对于大型文件而言,比较推荐这种方式,占用内存比较少。
  32.             byte[] buffer = new byte[1024];
  33.             int length = -1;
  34.             while ((length = fis.read(buffer, 0, 1024)) != -1) {
  35.                 md.update(buffer, 0, length);
  36.             }
  37.             fis.reset();
  38.             //转换并返回包含16个元素字节数组,返回数值范围为-128到127
  39.             byte[] md5Bytes  = md.digest();
  40.             StringBuffer hexValue = new StringBuffer();
  41.             for (int i = 0; i < md5Bytes.length; i++) {
  42.                 int val = ((int) md5Bytes[i]) & 0xff;//解释参见最下方
  43.                 if (val < 16) {
  44.                     /**
  45.                      * 如果小于16,那么val值的16进制形式必然为一位,
  46.                      * 因为十进制0,1...9,10,11,12,13,14,15 对应的 16进制为 0,1...9,a,b,c,d,e,f;
  47.                      * 此处高位补0。
  48.                      */
  49.                     hexValue.append("0");
  50.                 }
  51.                 //这里借助了Integer类的方法实现16进制的转换
  52.                 hexValue.append(Integer.toHexString(val));
  53.             }
  54.             return hexValue.toString();
  55.         } catch (Exception e) {
  56.             e.printStackTrace();
  57.             return "";
  58.         }
  59.     }
  60.     /**
  61.      *字符串经过md5加密成32位
  62.      */
  63.     public static String md5HashCode32Str(String plainText) {
  64.         try {
  65.             MessageDigest md = MessageDigest.getInstance("MD5");
  66.             md.update(plainText.getBytes());
  67.             byte[] md5Bytes  = md.digest();
  68.             StringBuffer hexValue = new StringBuffer();
  69.             for (int i = 0; i < md5Bytes.length; i++) {
  70.                 int val = ((int) md5Bytes[i]) & 0xff;//解释参见最下方
  71.                 if (val < 16) {
  72.                     /**
  73.                      * 如果小于16,那么val值的16进制形式必然为一位,
  74.                      * 因为十进制0,1...9,10,11,12,13,14,15 对应的 16进制为 0,1...9,a,b,c,d,e,f;
  75.                      * 此处高位补0。
  76.                      */
  77.                     hexValue.append("0");
  78.                 }
  79.                 //这里借助了Integer类的方法实现16进制的转换
  80.                 hexValue.append(Integer.toHexString(val));
  81.             }
  82.             return hexValue.toString();
  83.         } catch (Exception e) {
  84.             e.printStackTrace();
  85.             return "";
  86.         }
  87.     }
  88. }
复制代码
  1. package com.sun.minio.util;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.util.StringUtils;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.InputStream;
  7. import java.io.OutputStream;
  8. import java.net.URLEncoder;
  9. public class DownloadUtils {
  10.     private static final String JSON_APPLICATION = "application/json";
  11.     private static final Logger log = LoggerFactory.getLogger(DownloadUtils.class.getName());
  12.     public static boolean downloadFile( HttpServletResponse response, InputStream inputStream
  13.             , String objectName, long fileLen, String contentType
  14.             , boolean closeInputStream, long maxAge,String exportFileName) throws Exception {
  15.         String fileName = StringUtils.isEmpty(exportFileName)?objectName.substring(objectName.lastIndexOf("/")+1):exportFileName;
  16.         if (!StringUtils.isEmpty(contentType)) {
  17.             response.setContentType(contentType);
  18.         } else {
  19.             response.setContentType("application/octet-stream");
  20.         }
  21.         response.setCharacterEncoding("utf-8");
  22.         response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
  23.         response.setHeader("X-Actual-Content-Length", String.valueOf(fileLen));
  24.         cors(response, maxAge);
  25.         OutputStream out = response.getOutputStream();
  26.         byte[] buffer = new byte[1024];
  27.         int len;
  28.         try {
  29.             while ((len = inputStream.read(buffer)) != -1) {
  30.                 out.write(buffer, 0, len);
  31.             }
  32.         } catch (Exception e) {
  33.             log.info("download file error.e=" + e);
  34.             return false;
  35.         } finally {
  36.             if (closeInputStream) {
  37.                 inputStream.close();
  38.             }
  39.             out.flush();
  40.             out.close();
  41.         }
  42.         return true;
  43.     }
  44.     public static void cors(HttpServletResponse response, long maxAge) {
  45.         response.setHeader("Access-Control-Allow-Origin", "*");
  46.         response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
  47.         if (maxAge > 0) {
  48.             response.setHeader("Access-Control-Max-Age", String.valueOf(maxAge));
  49.             response.setHeader("Cache-Control", "max-age=" + maxAge);
  50.         }
  51.         response.setHeader("Access-Control-Allow-Headers", "*");
  52.         response.setHeader("Access-Control-Expose-Headers", "Cache-Control, Accept-Ranges, Content-Encoding, Content-Length, Content-Range, X-Actual-Content-Length, Content-Disposition");
  53.     }
  54. }
复制代码

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表