فهرست منبع

将获取文件的接口做额外的处理

Yangzw 1 ماه پیش
والد
کامیت
c3bf7c536f

+ 109 - 1
feifan-framework/feifan-common/src/main/java/cn/newfeifan/mall/framework/common/util/servlet/ServletUtils.java

@@ -12,8 +12,13 @@ import org.springframework.web.context.request.ServletRequestAttributes;
 import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.File;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
 import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Map;
 
 /**
@@ -41,8 +46,9 @@ public class ServletUtils {
      * @param response 响应
      * @param filename 文件名
      * @param content  附件内容
+     * @param request
      */
-    public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
+    public static void writeAttachment(HttpServletResponse response, String filename, byte[] content, HttpServletRequest request) throws IOException {
         // 设置 header 和 contentType
         if (filename.contains("mp4")) {
             response.setHeader("Content-Disposition", "inline");
@@ -58,6 +64,108 @@ public class ServletUtils {
         IoUtil.write(response.getOutputStream(), false, content);
     }
 
+    /**
+     * 为了适配ios能够视频浏览,在文件溜获取的位置加上一些头部信息
+     * @param content 内容
+     * @param reqRange range
+     * @param response 响应体
+     */
+    public static void transfer(byte[] content, String reqRange, HttpServletResponse response){
+        try {
+            File sf = fileTransition(content);
+            RspInfo ri= getPartFileRsp( sf, reqRange) ;
+            response.setContentLength((int)ri.content_Length);
+            response.setHeader("Content-Range", ri.content_Range);
+            response.setHeader("Accept-Ranges", "bytes");
+            response.setHeader("Content-Disposition", "inline");
+            response.setContentType("video/mp4");
+            response.setHeader("Access-Control-Allow-Origin","*");
+            response.setHeader("Cache-Control","no-cache");
+            response.setStatus(206);
+            sendToClient(ri, response.getOutputStream(), sf);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    public static RspInfo getPartFileRsp(File sf,String reqRange) throws Exception {
+        RspInfo rinfo = new RspInfo();
+
+/* 1、Range 类型 1)bytes=x...- 2)bytes=x...-x... //Range:(unit=first byte pos)-[last byte pos]
+如:Range: bytes=0- Range: bytes=0-801
+
+2、对应 Content-Range: bytes x...(开始读取位置)-y...(读取结束位置)/z...(文件总大小) //Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]
+如:Content-Range: bytes 0-800/801 //801:文件总大小
+*/
+        if(null!=reqRange){
+            String[] ranplits= reqRange.split("=");
+            if(ranplits.length!=2)throw new Exception("range format wrong ");
+            String lenstr=ranplits[1];
+            String[] flens=lenstr.split("-",-1);
+            if(flens.length!=2)throw new Exception("rangelen format wrong ");
+            long fpos =Long.valueOf(flens[0]);
+            long lpos= flens[1].length()>0?Long.valueOf(flens[1]):sf.length()-1; //表示文件读取文件大小
+
+            rinfo.skipLenth=fpos;
+            rinfo.content_Length=lpos-fpos+1;
+            rinfo.content_Range=ranplits[0]+" "+fpos+"-"+lpos+"/"+sf.length();
+        }
+        return rinfo;
+    }
+
+    public static void sendToClient(RspInfo rinfo , OutputStream os, File sf) {
+
+        RandomAccessFile raf;
+        try {
+            raf = new RandomAccessFile(sf, "r");
+            byte[] b=new byte[102400];
+            raf.seek(rinfo.skipLenth);
+            long readlen=rinfo.content_Length; //需要读取的字节长度
+            int clen=0;
+            while(readlen>0&&(clen=raf.read(b))!=-1){
+                if(readlen>clen){
+                    os.write(b,0,clen);
+                }else{
+                    os.write(b,0, (int)readlen);
+                }
+                readlen-=clen;
+            }
+            raf.close();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }finally{
+            if(os!=null){
+                try {
+                    os.flush();
+                    os.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * 将bute写入文件
+     * @param content 内容字节
+     * @return file
+     * @throws IOException 异常
+     */
+    public static File fileTransition(byte[] content) throws IOException{
+        File file = new File("data/file/videoTest.mp4");
+        if(!file.exists()){
+            file.mkdir();
+        }
+        Files.write(Paths.get("data/file/videoTest.mp4"), content);
+        return file;
+    }
+
+    static class RspInfo{
+        public long content_Length=-1;
+        public String content_Range="";
+        public long skipLenth=-1;
+    }
+
     /**
      * @param request 请求
      * @return ua

+ 1 - 1
feifan-module-infra/feifan-module-infra-biz/src/main/java/cn/newfeifan/mall/module/infra/controller/admin/codegen/CodegenController.java

@@ -145,7 +145,7 @@ public class CodegenController {
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         ZipUtil.zip(outputStream, paths, ins);
         // 输出
-        ServletUtils.writeAttachment(response, "codegen.zip", outputStream.toByteArray());
+        ServletUtils.writeAttachment(response, "codegen.zip", outputStream.toByteArray(), null);
     }
 
 }

+ 1 - 1
feifan-module-infra/feifan-module-infra-biz/src/main/java/cn/newfeifan/mall/module/infra/controller/admin/db/DatabaseDocController.java

@@ -72,7 +72,7 @@ public class DatabaseDocController {
         String downloadFileName = DOC_FILE_NAME + fileOutputType.getFileSuffix(); //下载后的文件名
         try {
             // 读取,返回
-            ServletUtils.writeAttachment(response, downloadFileName, FileUtil.readBytes(filePath));
+            ServletUtils.writeAttachment(response, downloadFileName, FileUtil.readBytes(filePath), null);
         } finally {
             handleDeleteFile(deleteFile, filePath);
         }

+ 7 - 1
feifan-module-infra/feifan-module-infra-biz/src/main/java/cn/newfeifan/mall/module/infra/controller/admin/file/FileController.java

@@ -81,7 +81,13 @@ public class FileController {
             response.setStatus(HttpStatus.NOT_FOUND.value());
             return;
         }
-        ServletUtils.writeAttachment(response, path, content);
+        if(path.contains("mp4")){
+            String range = request.getHeader("Range");
+            System.out.println("========Range:" + range);
+            ServletUtils.transfer(content, range,response);
+        } else {
+        ServletUtils.writeAttachment(response, path, content,request);
+        }
     }
 
     @GetMapping("/page")