Bläddra i källkod

:recycle: 更新视频下载部分逻辑,适配ios与mac

Twelve615 1 år sedan
förälder
incheckning
b050cbf659

+ 102 - 9
jlsb/jeecg-boot-module-system/src/main/java/org/jeecg/modules/system/controller/CommonController.java

@@ -1,8 +1,13 @@
 package org.jeecg.modules.system.controller;
 
 import cn.hutool.cache.file.LFUFileCache;
+import cn.hutool.http.HtmlUtil;
+import cn.hutool.http.useragent.Browser;
+import cn.hutool.http.useragent.UserAgent;
+import cn.hutool.http.useragent.UserAgentParser;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.google.common.base.Strings;
 import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.constant.CommonConstant;
@@ -27,10 +32,13 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
 import org.springframework.web.servlet.HandlerMapping;
 import org.springframework.web.servlet.ModelAndView;
 
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.net.URLDecoder;
+import java.util.Date;
+
 /**
  * <p>
  * 用户表 前端控制器
@@ -222,6 +230,8 @@ public class CommonController {
         if(oConvertUtils.isEmpty(imgPath) || imgPath=="null"){
             return;
         }
+        String userAgent = request.getHeader("User-Agent");
+        UserAgent parse = UserAgentParser.parse(userAgent);
         // 其余处理略
         InputStream inputStream = null;
         OutputStream outputStream = null;
@@ -245,6 +255,19 @@ public class CommonController {
                 //outputStream.write(cacheFile, 0, cacheFile.length);
                 inputStream = new ByteArrayInputStream(cacheFile);
                 log.info("视频缓存");
+                String browserName = parse.getBrowser().getName();
+                String osName = parse.getOs().getName();
+                if ((!Strings.isNullOrEmpty(browserName) && browserName.startsWith("Safari")) || (!Strings.isNullOrEmpty(osName) && osName.startsWith("iPhone"))) {
+                    sendVideo(request, response, file, file.getName());
+                } else {
+                    outputStream = response.getOutputStream();
+                    byte[] buf = new byte[512000];
+                    int len;
+                    while ((len = inputStream.read(buf)) > 0) {
+                        outputStream.write(buf, 0, len);
+                    }
+                    response.flushBuffer();
+                }
             } else {
                 // 内存使用太多不使用缓存
 /*                LFUFileCache fileCache = sysFileCacheService.getFileCache(CACHE_IMG_NAME);
@@ -253,19 +276,17 @@ public class CommonController {
                 inputStream = new ByteArrayInputStream(fileBytes);
                 log.info("其他文件缓存");*/
                 inputStream = new BufferedInputStream(new FileInputStream(filePath));
+                outputStream = response.getOutputStream();
+                byte[] buf = new byte[4096];
+                int len;
+                while ((len = inputStream.read(buf)) > 0) {
+                    outputStream.write(buf, 0, len);
+                }
+                response.flushBuffer();
             }
-            //inputStream = new BufferedInputStream(new FileInputStream(filePath));
-            outputStream = response.getOutputStream();
-            byte[] buf = new byte[4096];
-            int len;
-            while ((len = inputStream.read(buf)) > 0) {
-                outputStream.write(buf, 0, len);
-            }
-            response.flushBuffer();
         } catch (IOException e) {
             log.error("预览文件失败" + e.getMessage());
             response.setStatus(404);
-            e.printStackTrace();
         } finally {
             if (inputStream != null) {
                 try {
@@ -285,6 +306,78 @@ public class CommonController {
 
     }
 
+    private void sendVideo(HttpServletRequest request, HttpServletResponse response, File file, String fileName) throws FileNotFoundException, IOException {
+        RandomAccessFile randomFile = new RandomAccessFile(file, "r");//只读模式
+        long contentLength = randomFile.length();
+        String range = request.getHeader("Range");
+        int start = 0, end = 0;
+        if(range != null && range.startsWith("bytes=")){
+            String[] values = range.split("=")[1].split("-");
+            start = Integer.parseInt(values[0]);
+            if(values.length > 1){
+                end = Integer.parseInt(values[1]);
+            }
+        }
+        int requestSize = 0;
+        if(end != 0 && end > start){
+            requestSize = end - start + 1;
+        } else {
+            requestSize = Integer.MAX_VALUE;
+        }
+
+        response.setContentType("video/mp4");
+        response.setHeader("Accept-Ranges", "bytes");
+        response.setHeader("ETag", fileName);
+        response.setHeader("Last-Modified", new Date().toString());
+        //第一次请求只返回content length来让客户端请求多次实际数据
+        if(range == null){
+            response.setHeader("Content-length", contentLength + "");
+        }else{
+            //以后的多次以断点续传的方式来返回视频数据
+            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206
+            long requestStart = 0, requestEnd = 0;
+            String[] ranges = range.split("=");
+            if(ranges.length > 1){
+                String[] rangeDatas = ranges[1].split("-");
+                requestStart = Integer.parseInt(rangeDatas[0]);
+                if(rangeDatas.length > 1){
+                    requestEnd = Integer.parseInt(rangeDatas[1]);
+                }
+            }
+            long length = 0;
+            if(requestEnd > 0){
+                length = requestEnd - requestStart + 1;
+                response.setHeader("Content-length", "" + length);
+                response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);
+            }else{
+                length = contentLength - requestStart;
+                response.setHeader("Content-length", "" + length);
+                response.setHeader("Content-Range", "bytes "+ requestStart + "-" + (contentLength - 1) + "/" + contentLength);
+            }
+        }
+        ServletOutputStream out = response.getOutputStream();
+        int needSize = requestSize;
+        randomFile.seek(start);
+        while(needSize > 0){
+            byte[] buffer = new byte[512000];
+            int len = randomFile.read(buffer);
+            if(needSize < buffer.length){
+                out.write(buffer, 0, needSize);
+            } else {
+                out.write(buffer, 0, len);
+                if(len < buffer.length){
+                    break;
+                }
+            }
+            needSize -= buffer.length;
+        }
+        randomFile.close();
+        out.close();
+    }
+
+
+
+
 //	/**
 //	 * 下载文件
 //	 * 请求地址:http://localhost:8080/common/download/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}