Browse Source

Merge branch 'dev/2024/1101update-admin-Y' of feifan/mall-backend-admin into master

Yangzw 4 months ago
parent
commit
6b8226afa2

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

@@ -4,6 +4,7 @@ import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.servlet.ServletUtil;
 import cn.newfeifan.mall.framework.common.util.json.JsonUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.MediaType;
 import org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
@@ -12,15 +13,23 @@ 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;
 
+import static cn.hutool.core.io.FileUtil.getAbsolutePath;
+
 /**
  * 客户端工具类
  *
  * @author 非繁源码
  */
+@Slf4j
 public class ServletUtils {
 
     /**
@@ -41,8 +50,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 +68,113 @@ 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,String path){
+        try {
+            File sf = fileTransition(content,path);
+            log.info("=====file文件:{}",sf);
+            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 > 0? lpos-fpos-1:sf.length()-(fpos > 0?fpos-1:0);
+//            rinfo.content_Length=sf.length();
+            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,String path) throws IOException{
+        File file = new File(getAbsolutePath(path));
+        log.info("======file:{}",file);
+        log.info("===file.length:{}",file.length());
+        if(!file.exists()){
+            boolean newFile = file.createNewFile();
+            log.info("=====创建文件yse or no:{}",newFile);
+        }
+//        Files.write(Paths.get(path), 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);
         }

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

@@ -62,7 +62,7 @@ public class FileController {
     @GetMapping("/{configId}/get/**")
     @PermitAll
     @Operation(summary = "下载文件")
-    @Parameter(name = "configId", description = "配置编号",  required = true)
+    @Parameter(name = "configId", description = "配置编号", required = true)
     public void getFileContent(HttpServletRequest request,
                                HttpServletResponse response,
                                @PathVariable("configId") Long configId) throws Exception {
@@ -73,6 +73,7 @@ public class FileController {
         }
         // 解码,解决中文路径的问题 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/
         path = URLUtil.decode(path);
+        log.info("=====path:{}",path);
 
         // 读取内容
         byte[] content = fileService.getFileContent(configId, path);
@@ -81,7 +82,14 @@ public class FileController {
             response.setStatus(HttpStatus.NOT_FOUND.value());
             return;
         }
-        ServletUtils.writeAttachment(response, path, content);
+        if (path.contains("mp4")) {
+            String range = request.getHeader("Range");
+            log.info("========Range:{}", range);
+            ServletUtils.transfer(content, range, response, "/data/file/" + path);
+        } else {
+            log.info("===============开始获取文件");
+            ServletUtils.writeAttachment(response, path, content, request);
+        }
     }
 
     @GetMapping("/page")

+ 13 - 6
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/ProductSpuController.java

@@ -24,10 +24,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
 import static cn.newfeifan.mall.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
@@ -115,8 +112,18 @@ public class ProductSpuController {
     @Parameter(name = "spuIds", description = "spu 编号列表", required = true, example = "[1,2,3]")
     @PreAuthorize("@ss.hasPermission('product:spu:query')")
     public CommonResult<List<ProductSpuRespVO>> getSpuList(@RequestParam("spuIds") Collection<Long> spuIds) {
-        return success(ProductSpuConvert.INSTANCE.convertForSpuDetailRespListVO(
-                productSpuService.getSpuList(spuIds), productSkuService.getSkuListBySpuId(spuIds)));
+        List<ProductSpuRespVO> data = ProductSpuConvert.INSTANCE.convertForSpuDetailRespListVO(
+                productSpuService.getSpuList(spuIds), productSkuService.getSkuListBySpuId(spuIds));
+
+        List<ProductSpuRespVO> list = new ArrayList<>();
+        for (Long spuId : spuIds) {
+            for (ProductSpuRespVO vo : data) {
+                if(spuId.equals(vo.getId())){
+                    list.add(vo);
+                }
+            }
+        }
+        return success(list);
     }
 
     @GetMapping("/page")

+ 2 - 2
feifan-server/src/main/resources/application.yaml

@@ -12,8 +12,8 @@ spring:
   servlet:
     # 文件上传相关配置项
     multipart:
-      max-file-size: 16MB # 单个文件大小
-      max-request-size: 32MB # 设置总上传的文件大小
+      max-file-size: 100MB # 单个文件大小
+      max-request-size: 100MB # 设置总上传的文件大小
   mvc:
     pathmatch:
       matching-strategy: ANT_PATH_MATCHER # 解决 SpringFox 与 SpringBoot 2.6.x 不兼容的问题,参见 SpringFoxHandlerProviderBeanPostProcessor 类

+ 4 - 1
sql/mysql/建空库SQL/25_20241011.sql

@@ -31,4 +31,7 @@ ALTER TABLE member_user
     ADD COLUMN `visitor` bit(1) DEFAULT b'0' COMMENT '是否是游客 0:否 1:是';
 
 ALTER TABLE trade_order
-    ADD COLUMN `user_deleted` bit(1) DEFAULT b'0' COMMENT '用户是否删除';
+    ADD COLUMN `user_deleted` bit(1) DEFAULT b'0' COMMENT '用户是否删除';
+
+ALTER TABLE distri_pt_profit
+    ADD COLUMN `visitor_earnings` bigint NOT NULL DEFAULT '0' COMMENT '游客收益';