소스 검색

Merge remote-tracking branch 'origin/dev-lengfaqiang' into dev

# Conflicts:
#	pom.xml
#	sckw-modules/sckw-example/src/main/java/com/sckw/example/controller/ExcelExportController.java
#	sckw-modules/sckw-file/pom.xml
lengfaqiang 2 년 전
부모
커밋
52fbd48843

+ 6 - 6
README.md

@@ -26,8 +26,8 @@
 | *服务网关       | 采用 SpringCloud Gateway 框架扩展了多种功能例如:内网鉴权、请求体缓存、跨域配置、请求响应日志等                                             |
 | *负载均衡       | 采用 SpringCloud Loadbalancer 扩展支持了开发团队路由 便于多团队开发调试                                                      |
 | *RPC远程调用    | 采用 全新 Apache Dubbo 3.X + OpenFeign                                                                     |
-| 分布式限流熔断     | 采用 Alibaba Sentinel 源码集成便于调试扩展与二次开发 框架还为其增加了各种监控                                                       |
-| 分布式事务       | 采用 Alibaba Seata 源码集成对接了Nacos与各种监控 简化了搭建部署流程                                                           |                                                                        |
+| *分布式限流熔断    | 采用 Alibaba Sentinel 源码集成便于调试扩展与二次开发 框架还为其增加了各种监控                                                       |
+| *分布式事务      | 采用 Alibaba Seata 源码集成对接了Nacos与各种监控 简化了搭建部署流程                                                           |                                                                        |
 | 权限认证        | 采用 Sa-Token、Jwt 静态使用功能齐全 低耦合 高扩展                                                                       |
 | 权限注解        | 采用 Sa-Token 支持注解 登录校验、角色校验、权限校验、二级认证校验、HttpBasic校验、忽略校验角色与权限校验支持多种条件 如 `AND` `OR` 或 `权限 OR 角色` 等复杂表达式  |
 | *关系数据库      | 使用 MySQL                                                                                               |                                    
@@ -43,8 +43,8 @@
 | 数据库连接池      | 采用 HikariCP Spring官方内置连接池 配置简单 以性能与稳定性闻名天下/Druid                                                       |
 | *数据库主键      | 采用 雪花ID 基于时间戳的 有序增长 唯一ID 再也不用为分库分表 数据合并主键冲突重复而发愁                                                       |
 | 服务端与前端消息通信  | 援用现有mqtt                                                                                               |
-| *序列化         | 采用 Jackson Spring官方内置序列化 靠谱!!!                                                                         |
-| 分布式任务调度     | 采用 Xxl-Job 天生支持分布式 统一的管理中心                                                                             |
+| *序列化        | 采用 Jackson Spring官方内置序列化 靠谱!!!                                                                         |
+| *分布式任务调度    | 采用 Xxl-Job 天生支持分布式 统一的管理中心                                                                             |
 | 分布式日志中心     | 采用 ELK 业界成熟解决方案 实时收集所有服务的运行日志 快速发现定位问题                                                                 |
 | 分布式搜索引擎     | 采用 ElasticSearch以 Mybatis-Plus 方式操作 ElasticSearch                                                      |
 | *分布式消息队列    | 采用 SpringCloud-Stream + RabbitMQ                                                                       |
@@ -53,8 +53,8 @@
 | 短链接         | 购买现成产品                                                                                                 |
 | 接口文档        | 沿用现有接口文档系统                                                                                             |
 | 校验框架        | 采用 Validation 支持注解与工具类校验 注解支持国际化                                                                       |
-| *Excel框架     | 采用 Alibaba EasyExcel 基于插件化框架对其增加了很多功能 例如 自动合并相同内容 自动排列布局 字典翻译等                                         |
-| *工具类框架       | 采用 Hutool、Lombok 上百种工具覆盖90%的使用需求 基于注解自动生成 get set 等简化框架大量代码                                            |
+| *Excel框架    | 采用 Alibaba EasyExcel 基于插件化框架对其增加了很多功能 例如 自动合并相同内容 自动排列布局 字典翻译等                                         |
+| *工具类框架      | 采用 Hutool、Lombok 上百种工具覆盖90%的使用需求 基于注解自动生成 get set 等简化框架大量代码                                            |
 | 服务监控框架      | 采用 SpringBoot-Admin 基于SpringBoot官方 actuator 探针机制实时监控服务状态 框架还为其扩展了在线日志查看监控                              |
 | 全方位监控报警     | 采用 Prometheus、Grafana 多样化采集 多模板大屏展示 实时报警监控 提供详细的搭建文档                                                   |
 | 链路追踪        | 采用 Apache SkyWalking 还在为请求不知道去哪了 到哪出了问题而烦恼吗用了它即可实时查看请求经过的每一处每一个节点                                      |

+ 2 - 2
sckw-common/sckw-common-core/src/main/java/com/sckw/core/model/base/BaseModel.java

@@ -28,7 +28,7 @@ public class BaseModel implements Serializable {
 	/**
 	 * 状态:0正常/1锁定
 	 */
-	private Integer status;
+	private Integer status=0;
 
 	/**
 	 * 创建人
@@ -67,6 +67,6 @@ public class BaseModel implements Serializable {
 	/**
 	 * 删除标识(0正常/-1删除)
 	 */
-	private Integer delFlag;
+	private Integer delFlag=0;
 
 }

+ 26 - 0
sckw-common/sckw-common-excel/src/main/java/com/sckw/excel/common/StringConstant.java

@@ -0,0 +1,26 @@
+package com.sckw.excel.common;
+
+/**
+ * @description:    定义字符串常量
+ * @author: LengFaQiang
+ * @copyright
+ * @create: 2022-01-27 16:02
+ **/
+public final class StringConstant {
+    public static final String LEFT_SEPARATOR = "/";
+    public static final String LEFT_SEPARATORS = "//";
+    public static final String RIGHT_SEPARATOR = "\\";
+    public static final String COLON = ":";
+    public static final String POINT = ".";
+    public static final String COMMA=",";
+    public static final String HTTP_STRING = "http";
+    public static final String HTTPS_STRING = "https";
+    public static final String B = "B";
+    public static final String KB = "KB";
+    public static final String MB = "MB";
+    public static final String G = "G";
+    public static final String GB = "GB";
+
+    public StringConstant() {
+    }
+}

+ 33 - 9
sckw-modules/sckw-example/src/main/java/com/sckw/example/controller/ExcelExportController.java

@@ -1,7 +1,9 @@
 package com.sckw.example.controller;
 
 import com.alibaba.fastjson.JSONObject;
+import com.sckw.core.utils.IdWorker;
 import com.sckw.core.utils.StringUtils;
+import com.sckw.core.web.constant.HttpStatus;
 import com.sckw.core.web.response.HttpResult;
 import com.sckw.example.dao.KwsDeptDao;
 import com.sckw.example.model.KwsDept;
@@ -13,6 +15,8 @@ import com.sckw.excel.utils.DateUtil;
 import com.sckw.excel.utils.ExcelUtil;
 import com.sckw.file.api.dubbo.FileApiDubboService;
 //import io.seata.spring.annotation.GlobalTransactional;
+import io.seata.core.context.RootContext;
+import io.seata.spring.annotation.GlobalTransactional;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
@@ -28,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import java.io.File;
 import java.io.UnsupportedEncodingException;
+import java.util.Date;
 import java.util.List;
 
 @Slf4j
@@ -126,17 +131,36 @@ public class ExcelExportController {
      * 分布式事务验证
      * @return
      */
-    //@GlobalTransactional
+    @GlobalTransactional(rollbackFor = Exception.class,name = "example-seata-service-group")
     @RequestMapping(value = "globalTransactionalDemo",method = RequestMethod.GET)
     public HttpResult globalTransactionalDemo() {
-        //auth 服务 调用example实现的dubbo接口
-        KwsDept kwsDept = new KwsDept();
-        kwsDept.setName("张三");
-        kwsDept.setAccount("张三");
-        kwsDept.setParentIds("2");
-        int i= kwsDeptDao.insert(kwsDept);
-        HttpResult result= fileApiDubboService.selectAll();
-        log.info(JSONObject.toJSONString(result));
+        KwsDept dos = new KwsDept();
+        HttpResult result= null;
+        result.setMsg(HttpStatus.SUCCESS_MESSAGE);
+        try {
+            dos.setId(new IdWorker(1).nextId());
+            dos.setSystemType("1");
+            dos.setAccount("张三");
+            dos.setPassword("password");
+            dos.setName("张三");
+            dos.setTelephone("4564789113");
+            dos.setPhoto("44546545");
+            dos.setEmail("45456454");
+            dos.setClientId("7879814");
+            dos.setIsMain(0);
+            dos.setCreateBy(123L);
+            dos.setUpdateBy(123L);
+            dos.setCreateTime(new Date());
+            dos.setUpdateTime(new Date());
+            kwsDeptDao.insert(dos);
+            String xid = RootContext.getXID();
+            result = fileApiDubboService.selectAll();
+            log.info(JSONObject.toJSONString(result));
+        } catch (Exception e) {
+            result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
+            result.setMsg(e.getMessage());
+            throw new RuntimeException(e);
+        }
         return result;
     }
 }

+ 6 - 0
sckw-modules/sckw-example/src/main/java/com/sckw/example/dubbo/FileApiServiceImpl.java

@@ -1,10 +1,13 @@
 package com.sckw.example.dubbo;
 
 import com.sckw.core.web.response.HttpResult;
+import com.sckw.excel.common.NumberConstant;
 import com.sckw.file.api.dubbo.FileApiDubboService;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.math.BigDecimal;
+
 /**
  * @author lfdc
  * @description fileDubbo调用
@@ -25,6 +28,9 @@ public class FileApiServiceImpl implements FileApiDubboService {
 
     @Override
     public HttpResult selectAll() {
+        BigDecimal bigDecimal = new BigDecimal(NumberConstant.ZERO);
+        BigDecimal bigDecimal1 = new BigDecimal(NumberConstant.SIX);
+        BigDecimal divide = bigDecimal1.divide(bigDecimal);
         return null;
     }
 }

+ 10 - 2
sckw-modules/sckw-example/src/main/java/com/sckw/example/model/KwsDept.java

@@ -1,5 +1,6 @@
 package com.sckw.example.model;
 
+import com.sckw.core.model.base.BaseModel;
 import lombok.Data;
 
 /**
@@ -8,11 +9,18 @@ import lombok.Data;
  * @date 2023/6/19 0019
  */
 @Data
-public class KwsDept  {
+public class KwsDept  extends BaseModel {
 
+    private Long id;
     private String name;
     private String parentIds;
-//    private String contacts;
+    private String password;
     private String account;
+    private String systemType;
+    private String telephone;
+    private String email;
+    private String clientId;
+    private String photo;
+    private Integer isMain;
 
 }

+ 222 - 18
sckw-modules/sckw-example/src/main/resources/mapper/KwsDeptDao.xml

@@ -1,35 +1,239 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.sckw.example.dao.KwsDeptDao">
-  <resultMap id="BaseResultMap" type="com.sckw.example.model.KwsDept">
-    <result column="account" property="account" />
-    <result column="parent_ids" property="parentIds" />
-    <result column="name" property="name" />
-  </resultMap>
-
-    <insert id="insert" parameterType="com.sckw.example.model.KwsDept">
-        insert into sckw_system.kws_user
+    <resultMap id="BaseResultMap" type="com.sckw.example.model.KwsDept">
+        <id column="kws_user_id" jdbcType="BIGINT" property="id" />
+        <result column="system_type" jdbcType="INTEGER" property="systemType" />
+        <result column="account" jdbcType="VARCHAR" property="account" />
+        <result column="password" jdbcType="VARCHAR" property="password" />
+        <result column="name" jdbcType="VARCHAR" property="name" />
+        <result column="telephone" jdbcType="VARCHAR" property="telephone" />
+        <result column="photo" jdbcType="VARCHAR" property="photo" />
+        <result column="email" jdbcType="VARCHAR" property="email" />
+        <result column="client_id" jdbcType="VARCHAR" property="clientId" />
+        <result column="is_main" jdbcType="INTEGER" property="isMain" />
+        <result column="remark" jdbcType="VARCHAR" property="remark" />
+        <result column="status" jdbcType="INTEGER" property="status" />
+        <result column="create_by" jdbcType="BIGINT" property="createBy" />
+        <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
+        <result column="update_by" jdbcType="BIGINT" property="updateBy" />
+        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
+        <result column="del_flag" jdbcType="INTEGER" property="delFlag" />
+    </resultMap>
+    <sql id="Base_Column_List">
+         id as kws_user_id,  system_type as kws_user_system_type,  account as kws_user_account,
+     `password` as `kws_user_password`,  `name` as `kws_user_name`,  telephone as kws_user_telephone,
+     photo as kws_user_photo,  email as kws_user_email,  client_id as kws_user_client_id,
+     is_main as kws_user_is_main,  remark as kws_user_remark,  `status` as `kws_user_status`,
+     create_by as kws_user_create_by,  create_time as kws_user_create_time,
+     update_by as kws_user_update_by,  update_time as kws_user_update_time,
+     del_flag as kws_user_del_flag
+    </sql>
+    <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column_List" />
+        from kws_user
+        where  id = #{id,jdbcType=BIGINT}
+    </select>
+    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+        delete from kws_user
+        where id = #{id,jdbcType=BIGINT}
+    </delete>
+    <insert id="insert" parameterType="com.sckw.example.dao.KwsDeptDao">
+        insert into kws_user (id, system_type, account,
+                              `password`, `name`, telephone,
+                              photo, email, client_id,
+                              is_main, remark, `status`,
+                              create_by, create_time, update_by,
+                              update_time, del_flag)
+        values (#{id,jdbcType=BIGINT}, #{systemType,jdbcType=INTEGER}, #{account,jdbcType=VARCHAR},
+                #{password,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{telephone,jdbcType=VARCHAR},
+                #{photo,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{clientId,jdbcType=VARCHAR},
+                #{isMain,jdbcType=INTEGER}, #{remark,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER},
+                #{createBy,jdbcType=BIGINT}, #{createTime,jdbcType=TIMESTAMP}, #{updateBy,jdbcType=BIGINT},
+                #{updateTime,jdbcType=TIMESTAMP}, #{delFlag,jdbcType=INTEGER})
+    </insert>
+    <insert id="insertSelective" parameterType="com.sckw.example.dao.KwsDeptDao">
+        insert into kws_user
         <trim prefix="(" suffix=")" suffixOverrides=",">
-            <if test="name != null">
-                name,
+            <if test="id != null">
+                id,
+            </if>
+            <if test="systemType != null">
+                system_type,
             </if>
             <if test="account != null">
-                contacts,
+                account,
+            </if>
+            <if test="password != null">
+                `password`,
+            </if>
+            <if test="name != null">
+                `name`,
+            </if>
+            <if test="telephone != null">
+                telephone,
+            </if>
+            <if test="photo != null">
+                photo,
+            </if>
+            <if test="email != null">
+                email,
+            </if>
+            <if test="clientId != null">
+                client_id,
+            </if>
+            <if test="isMain != null">
+                is_main,
+            </if>
+            <if test="remark != null">
+                remark,
+            </if>
+            <if test="status != null">
+                `status`,
+            </if>
+            <if test="createBy != null">
+                create_by,
             </if>
-            <if test="parentIds != null">
-                parent_ids,
+            <if test="createTime != null">
+                create_time,
+            </if>
+            <if test="updateBy != null">
+                update_by,
+            </if>
+            <if test="updateTime != null">
+                update_time,
+            </if>
+            <if test="delFlag != null">
+                del_flag,
             </if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
-            <if test="name != null">
-                #{name,jdbcType=VARCHAR},
+            <if test="id != null">
+                #{id,jdbcType=BIGINT},
+            </if>
+            <if test="systemType != null">
+                #{systemType,jdbcType=INTEGER},
             </if>
             <if test="account != null">
                 #{account,jdbcType=VARCHAR},
             </if>
-            <if test="parentIds != null">
-                #{parentIds,jdbcType=VARCHAR},
+            <if test="password != null">
+                #{password,jdbcType=VARCHAR},
+            </if>
+            <if test="name != null">
+                #{name,jdbcType=VARCHAR},
+            </if>
+            <if test="telephone != null">
+                #{telephone,jdbcType=VARCHAR},
+            </if>
+            <if test="photo != null">
+                #{photo,jdbcType=VARCHAR},
+            </if>
+            <if test="email != null">
+                #{email,jdbcType=VARCHAR},
+            </if>
+            <if test="clientId != null">
+                #{clientId,jdbcType=VARCHAR},
+            </if>
+            <if test="isMain != null">
+                #{isMain,jdbcType=INTEGER},
+            </if>
+            <if test="remark != null">
+                #{remark,jdbcType=VARCHAR},
+            </if>
+            <if test="status != null">
+                #{status,jdbcType=INTEGER},
+            </if>
+            <if test="createBy != null">
+                #{createBy,jdbcType=BIGINT},
+            </if>
+            <if test="createTime != null">
+                #{createTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="updateBy != null">
+                #{updateBy,jdbcType=BIGINT},
+            </if>
+            <if test="updateTime != null">
+                #{updateTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="delFlag != null">
+                #{delFlag,jdbcType=INTEGER},
             </if>
         </trim>
     </insert>
-</mapper>
+    <update id="updateByPrimaryKeySelective" parameterType="com.sckw.example.dao.KwsDeptDao">
+        update kws_user
+        <set>
+            <if test="systemType != null">
+                system_type = #{systemType,jdbcType=INTEGER},
+            </if>
+            <if test="account != null">
+                account = #{account,jdbcType=VARCHAR},
+            </if>
+            <if test="password != null">
+                `password` = #{password,jdbcType=VARCHAR},
+            </if>
+            <if test="name != null">
+                `name` = #{name,jdbcType=VARCHAR},
+            </if>
+            <if test="telephone != null">
+                telephone = #{telephone,jdbcType=VARCHAR},
+            </if>
+            <if test="photo != null">
+                photo = #{photo,jdbcType=VARCHAR},
+            </if>
+            <if test="email != null">
+                email = #{email,jdbcType=VARCHAR},
+            </if>
+            <if test="clientId != null">
+                client_id = #{clientId,jdbcType=VARCHAR},
+            </if>
+            <if test="isMain != null">
+                is_main = #{isMain,jdbcType=INTEGER},
+            </if>
+            <if test="remark != null">
+                remark = #{remark,jdbcType=VARCHAR},
+            </if>
+            <if test="status != null">
+                `status` = #{status,jdbcType=INTEGER},
+            </if>
+            <if test="createBy != null">
+                create_by = #{createBy,jdbcType=BIGINT},
+            </if>
+            <if test="createTime != null">
+                create_time = #{createTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="updateBy != null">
+                update_by = #{updateBy,jdbcType=BIGINT},
+            </if>
+            <if test="updateTime != null">
+                update_time = #{updateTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="delFlag != null">
+                del_flag = #{delFlag,jdbcType=INTEGER},
+            </if>
+        </set>
+        where id = #{id,jdbcType=BIGINT}
+    </update>
+    <update id="updateByPrimaryKey" parameterType="com.sckw.example.dao.KwsDeptDao">
+        update kws_user
+        set system_type = #{systemType,jdbcType=INTEGER},
+            account = #{account,jdbcType=VARCHAR},
+            `password` = #{password,jdbcType=VARCHAR},
+            `name` = #{name,jdbcType=VARCHAR},
+            telephone = #{telephone,jdbcType=VARCHAR},
+            photo = #{photo,jdbcType=VARCHAR},
+            email = #{email,jdbcType=VARCHAR},
+            client_id = #{clientId,jdbcType=VARCHAR},
+            is_main = #{isMain,jdbcType=INTEGER},
+            remark = #{remark,jdbcType=VARCHAR},
+            `status` = #{status,jdbcType=INTEGER},
+            create_by = #{createBy,jdbcType=BIGINT},
+            create_time = #{createTime,jdbcType=TIMESTAMP},
+            update_by = #{updateBy,jdbcType=BIGINT},
+            update_time = #{updateTime,jdbcType=TIMESTAMP},
+            del_flag = #{delFlag,jdbcType=INTEGER}
+        where id = #{id,jdbcType=BIGINT}
+    </update>
+</mapper>

+ 23 - 0
sckw-modules/sckw-file/pom.xml

@@ -48,6 +48,12 @@
             <artifactId>sckw-system-api</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.sckw</groupId>
+            <artifactId>sckw-file-api</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <!--alibaba oss-->
         <dependency>
             <groupId>com.sckw</groupId>
             <artifactId>sckw-common-seata</artifactId>
@@ -115,4 +121,21 @@
         </dependency>
 
     </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
 </project>

+ 46 - 16
sckw-modules/sckw-file/src/main/java/com/sckw/file/controller/FileApiController.java

@@ -3,12 +3,15 @@ package com.sckw.file.controller;
 import com.sckw.core.web.constant.HttpStatus;
 import com.sckw.core.web.response.HttpResult;
 import com.sckw.file.service.FileService;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
 import java.util.Map;
 
 /**
@@ -47,19 +50,6 @@ public class FileApiController {
 
     }
 
-    /**
-     * feign接收上传文件至OSS
-     *
-     * @param file
-     * @return
-     */
-    @RequestMapping(value = "/fileFeignUpload", method = RequestMethod.POST)
-    public HttpResult fileFeignUpload(@RequestParam("file") MultipartFile file) {
-        //获取上传文件
-        return fileService.uploadFile(file);
-
-    }
-
     /**
      * 批量上传文件至OSS
      * @param file
@@ -77,13 +67,53 @@ public class FileApiController {
      * @return
      */
     @GetMapping("/fileDownload")
-    public HttpResult fileDownload() {
-        String fileName = "https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/kll/uploads/20230605/14633197602917990420230605demo.txt";
+    public HttpResult fileDownload(String fileName) {
+        try {
+            fileService.fileDownload(fileName);
+            return HttpResult.ok();
+        } catch (Exception e) {
+            log.error("文件下载失败:{}",e.getMessage(),e);
+            return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE,e.getMessage());
+        }
+    }
+
+    /**
+     * oss删除文件
+     * @param fileName  kll/uploads/20230621/07ccbec381a011d121a215719199ac49.html
+     * @return
+     */
+    @GetMapping("/remove")
+    public HttpResult remove(String fileName) {
         //获取上传文件
-        fileService.fileDownload(fileName);
+        fileService.remove(fileName);
         return HttpResult.ok();
     }
 
+    /***
+     * 批量下载(zip)
+     * @param fileAllName
+     * @param response
+     * @throws IOException
+     * fileAllName为前端传过来的多个文件路径字符串,用逗号隔开('filePath/file.xsl','filePath/file1.xsl','filePath/file2.xsl')
+     */
+    @RequestMapping("downAllOssFile")
+    @ResponseBody
+    public HttpResult downAllOssFile(@RequestParam("fileAllName") String fileAllName, HttpServletRequest request, HttpServletResponse response) {
+        return fileService.downAllOssFile(fileAllName,request,response);
+    }
+
+    /**
+     * feign接收上传文件至OSS
+     *
+     * @param file
+     * @return
+     */
+    @RequestMapping(value = "/fileFeignUpload", method = RequestMethod.POST)
+    public HttpResult fileFeignUpload(@RequestParam("file") MultipartFile file) {
+        //获取上传文件
+        return fileService.uploadFile(file);
+    }
+
     /**
      * file-feign-demo
      * @param userName

+ 103 - 6
sckw-modules/sckw-file/src/main/java/com/sckw/file/service/FileService.java

@@ -1,19 +1,23 @@
 package com.sckw.file.service;
 
 
+import com.aliyun.oss.model.OSSObject;
 import com.sckw.core.utils.IdWorker;
 import com.sckw.core.utils.StringUtils;
 import com.sckw.core.web.constant.HttpStatus;
 import com.sckw.core.web.response.HttpResult;
 import com.sckw.excel.common.NumberConstant;
+import com.sckw.excel.common.StringConstant;
 import com.sckw.file.common.enums.FileEnum;
 import com.sckw.file.dao.KwsFileInfoDao;
 import com.sckw.file.model.FileInfo;
 import com.sckw.file.utils.FileUtils;
+import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FilenameUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.util.ObjectUtils;
@@ -21,8 +25,14 @@ import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.*;
 import java.math.BigDecimal;
+import java.net.URLEncoder;
 import java.util.*;
+import java.util.zip.Adler32;
+import java.util.zip.CheckedOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 
 /**
@@ -37,6 +47,18 @@ import java.util.*;
 @Service
 public class FileService {
 
+    @Value("${aliyun.oss.endpoint}")
+    private String oss_endpoint;
+
+    @Value("${aliyun.oss.accessKeyId}")
+    private String oss_accessKeyId;
+
+    @Value("${aliyun.oss.secret}")
+    private String oss_accessKeySecret;
+
+    @Value("${aliyun.oss.bucket}")
+    public String oss_bucketName;
+
     @Autowired
     KwsFileInfoDao fileInfoDao;
 
@@ -61,7 +83,7 @@ public class FileService {
         //获取上传文件的原始文件名
         String oFileName = file.getOriginalFilename();
         //文件大小
-        BigDecimal fileSize = FileUtils.getFileSize(file, "KB");
+        BigDecimal fileSize = FileUtils.getFileSize(file, StringConstant.KB);
         FileInfo fileInfo = new FileInfo();
         fileInfo.setOriginalName(oFileName);
         //获取文件后缀
@@ -153,19 +175,94 @@ public class FileService {
     /**
      * OSS下载文件/获取文件地址
      *
-     * @return
+     * @param fileName kll/uploads/20230621/07ccbec381a011d121a215719199ac49.html
      */
     public void fileDownload(String fileName) {
         HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
-        FileUtils.downloadByUrl(response,fileName);
-        FileUtils.downOSSFile(fileName, response);
-//        FileUtils.downloadByFileName(fileName);
+        FileUtils.downloadByUrl(response, fileName);
+    }
+
+
+    public void remove(String fileName) {
+        String str = StringConstant.HTTP_STRING
+                + StringConstant.COLON
+                + StringConstant.LEFT_SEPARATORS
+                + oss_bucketName
+                + StringConstant.POINT
+                + oss_endpoint
+                + StringConstant.LEFT_SEPARATOR;
+        String fileNameSubstring = StringUtils.substring(fileName, str.length() + 1);
+        FileUtils.remove(fileName);
     }
 
     public HttpResult selectAll() {
         BigDecimal bigDecimal1 = new BigDecimal(NumberConstant.ZERO);
         BigDecimal bigDecimal2 = new BigDecimal(NumberConstant.SIX);
         BigDecimal multiply = bigDecimal2.divide(bigDecimal1);
-        return HttpResult.ok("",multiply);
+        return HttpResult.ok("", multiply);
+    }
+
+    public HttpResult downAllOssFile(String fileAllName,HttpServletRequest request, HttpServletResponse response) {
+        try {
+            String momentFileName = "全部资源下载.zip";
+            // 创建临时文件
+            File zipFile = File.createTempFile("批量下载", ".zip");
+            FileOutputStream f = new FileOutputStream(zipFile);
+            CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
+            // 用于将数据压缩成Zip文件格式
+            ZipOutputStream zos = new ZipOutputStream(csum);
+            String[] files = fileAllName.split(",");
+            for (String string : files) {
+                String fName = string.trim();
+                String eachFileName = fName.substring(fName.lastIndexOf("/")+1);
+                String tmp = fName.substring(0,fName.lastIndexOf("/"));
+                tmp = tmp.substring(tmp.lastIndexOf("/")+1);
+                String fileName = tmp + "/" + eachFileName;
+                OSSObject ossObject =  FileUtils.downloadOssFile(response.getOutputStream(), fileName);
+                InputStream inputStream = ossObject.getObjectContent();
+                zos.putNextEntry(new ZipEntry(eachFileName));
+                int bytesRead;
+                // 向压缩文件中输出数据
+                while((bytesRead = inputStream.read())!=-1){
+                    zos.write(bytesRead);
+                }
+                inputStream.close();
+                zos.closeEntry();
+            }
+            zos.close();
+            String header = request.getHeader("User-Agent").toUpperCase();
+            if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) {
+                momentFileName = URLEncoder.encode(momentFileName, "utf-8");
+                momentFileName = momentFileName.replace("+", "%20");    //IE下载文件名空格变+号问题
+            } else {
+                momentFileName = new String(momentFileName.getBytes(), "ISO8859-1");
+            }
+            response.reset();
+            response.setContentType("text/plain");
+            response.setContentType("application/octet-stream; charset=utf-8");
+            response.setHeader("Location", momentFileName);
+            response.setHeader("Cache-Control", "max-age=0");
+            response.setHeader("Content-Disposition", "attachment; filename=" + momentFileName);
+            FileInputStream fis = new FileInputStream(zipFile);
+            BufferedInputStream buff = new BufferedInputStream(fis);
+            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
+            byte[] car = new byte[1024];
+            int l=0;
+            while (l < zipFile.length()) {
+                int j = buff.read(car, 0, 1024);
+                l += j;
+                out.write(car, 0, j);
+            }
+            // 关闭流
+            fis.close();
+            buff.close();
+            out.close();
+            // 删除临时文件
+            zipFile.delete();
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.info("batch list down file error :{}",e.getMessage(),e);
+        }
+        return null;
     }
 }

+ 36 - 0
sckw-modules/sckw-file/src/main/java/com/sckw/file/service/dubbo/FileApiServiceImpl.java

@@ -0,0 +1,36 @@
+package com.sckw.file.service.dubbo;
+
+import com.sckw.core.web.response.HttpResult;
+import com.sckw.excel.common.NumberConstant;
+import com.sckw.file.api.dubbo.FileApiDubboService;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.math.BigDecimal;
+
+/**
+ * @author lfdc
+ * @description fileDubbo调用
+ * @date 2023/6/20 0020
+ */
+@DubboService(group = "design", version = "2.0.0")
+public class FileApiServiceImpl implements FileApiDubboService {
+
+    @Override
+    public HttpResult fileUpload(String str, byte[] fileByte) {
+        return null;
+    }
+
+    @Override
+    public HttpResult fileUploadTodubbo(MultipartFile file) {
+        return null;
+    }
+
+    @Override
+    public HttpResult selectAll() {
+        BigDecimal bigDecimal = new BigDecimal(NumberConstant.ZERO);
+        BigDecimal bigDecimal1 = new BigDecimal(NumberConstant.SIX);
+        BigDecimal divide = bigDecimal1.divide(bigDecimal);
+        return null;
+    }
+}

+ 151 - 17
sckw-modules/sckw-file/src/main/java/com/sckw/file/utils/FileUtils.java

@@ -91,6 +91,7 @@ public class FileUtils {
 
     /**
      * 获取指定文件或文件夹的后缀名
+     *
      * @param fileName 文件名称
      * @return
      */
@@ -108,10 +109,10 @@ public class FileUtils {
      */
     public static Map<String, String> uploadFileByInfo(MultipartFile file, FileEnum fileEnum) {
         Map<String, String> infoMap = new HashMap<>();
+        //创建OSSClient实例
+        defalutOSS();
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
         try {
-            //创建OSSClient实例
-            defalutOSS();
-            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
             //容器不存在,就创建
             if (!ossClient.doesBucketExist(bucketName)) {
                 ossClient.createBucket(bucketName);
@@ -133,7 +134,7 @@ public class FileUtils {
             //2021/02/02/01.jpg
             String timeUrl = new DateTime().toString("yyyyMMdd");
             fileName = timeUrl + "/" + fileName;
-            String filePath = BASE_DIR + fileName+fileSuffix;
+            String filePath = BASE_DIR + fileName + fileSuffix;
             //调用方法实现上传
             ossClient.putObject(bucketName, filePath, inputStream);
             //上传后的文件地址
@@ -142,13 +143,20 @@ public class FileUtils {
             ossClient.shutdown();
             //上传之后文件路径
             //https://yygh-atguigu.oss-cn-beijing.aliyuncs.com/01.jpg
-            String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
+//            String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
+            //绝对路径 "https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/+ filePath;"
+//            String url = StringConstant.HTTPS_STRING+StringConstant.COLON+StringConstant.LEFT_SEPARATORS + bucketName + StringConstant.POINT + endpoint + StringConstant.LEFT_SEPARATOR+ filePath;
+            //相对路径
+            String url = filePath;
             //返回 上传文件地址
             infoMap.put("filePath", url);
         } catch (IOException e) {
+            infoMap.put("filePath", null);
+            //关闭OSSClient。
+            ossClient.shutdown();
             e.printStackTrace();
             log.error("oss-upload-file-error:{}", e.getMessage(), e);
-           throw new RuntimeException("oss-upload-file-error:"+e.getMessage());
+            throw new RuntimeException("oss-upload-file-error:" + e.getMessage());
         }
         return infoMap;
     }
@@ -163,6 +171,9 @@ public class FileUtils {
      * @return
      */
     public static String uploadFile(MultipartFile file, FileEnum fileEnum) {
+        // 私有云要关闭CNAME
+        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
+        conf.setSupportCname(false);
         try {
             //创建OSSClient实例
             defalutOSS();
@@ -187,8 +198,11 @@ public class FileUtils {
             String timeUrl = new DateTime().toString("yyyyMMdd");
             fileName = timeUrl + "/" + fileName;
             String filePath = BASE_DIR + fileName;
+            /**设置上传内容类型*/
+            ObjectMetadata objectMeta = new ObjectMetadata();
+            objectMeta.setContentType(FileUtils.getContentTypeByOSS(file.getOriginalFilename()));
             //调用方法实现上传
-            ossClient.putObject(bucketName, filePath, inputStream);
+            ossClient.putObject(bucketName, filePath, inputStream,objectMeta);
             //上传后的文件地址
 //            String url1 = getUrl(ossClient, bucketName, filePath);
 //            System.out.println(url1);
@@ -252,7 +266,6 @@ public class FileUtils {
      */
     public static BigDecimal getFileSize(MultipartFile file, String type) {
         long size = file.getSize();
-//        DecimalFormat df = new DecimalFormat("#.00");
         BigDecimal bigDecimal = new BigDecimal(NumberConstant.ZERO);
         switch (type) {
             case "B":
@@ -307,6 +320,11 @@ public class FileUtils {
         return AliyunOssFileTypeEnum.TXT.getText();
     }
 
+    /**
+     *
+     * @param fileName
+     * @param response
+     */
     public static void downOSSFile(String fileName, HttpServletResponse response) {
         BufferedInputStream input = null;
         OutputStream outputStream = null;
@@ -354,15 +372,19 @@ public class FileUtils {
      *
      * @param response response
      * @param fileName 文件名字,带后缀,例子:postman.txt
-     *                 文件全路径 https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/kll/uploads/20230605/146325493677821952598454132.txt
+     *                 文件全路径 kll/uploads/20230605/146325493677821952598454132.txt 去除“https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/”
      */
     public static void downloadByFileName(HttpServletResponse response, String fileName) {
         defalutOSS();
         OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
         OSSObject ossObject = ossClient.getObject(bucketName, fileName);
+        boolean exist = ossClient.doesObjectExist(bucketName, fileName);
+        if (!exist) {
+            throw new RuntimeException("下载文件不存在!");
+        }
         String contentType = ossObject.getObjectMetadata().getContentType();
         String contentType1 = getContentType(fileName);
-        System.out.println("contentType:" + contentType);
+//        System.out.println("contentType:" + contentType);
 //        System.out.println("contentType1:" + contentType1);
         //设置响应内容类型,当设置了ContentType为“image/jpg”时,浏览器可以直接显示图片;
         response.setContentType(contentType);
@@ -370,7 +392,8 @@ public class FileUtils {
         try {
             BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
             //通知浏览器以附件形式下载
-            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
+//            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
+            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8").replaceAll("\\+", "%20"));
             byte[] car = new byte[1024];
             int len = 0;
             while ((len = in.read(car)) != -1) {
@@ -563,7 +586,7 @@ public class FileUtils {
      */
     public static String getUrl(OSS ossClient, String bucketName, String key) {
         //设置URl过期时间为99年:3600L*1000*24*365*99
-        Date expiration = new Date( System.currentTimeMillis()+ 3600L * 1000 * 24 * 365 * 99);
+        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 99);
         GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key);
         generatePresignedUrlRequest.setExpiration(expiration);
         URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
@@ -593,7 +616,9 @@ public class FileUtils {
             BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
             while (true) {
                 String line = reader.readLine();
-                if (line == null) break;
+                if (line == null) {
+                    break;
+                }
 
                 System.out.println("\n" + line);
             }
@@ -659,20 +684,20 @@ public class FileUtils {
      * 通过oss的完整key下载
      *
      * @param response response
-     * @param url      全路径的url地址
+     * @param url      全路径的url地址 kll/uploads/20230621/07ccbec381a011d121a215719199ac49.html
      */
     public static void downloadByUrl(HttpServletResponse response, String url) {
         downloadByFileName(response, url);
     }
 
     /**
-     * @Title:downloadToFile
-     * @Description: 下载文件到本地
      * @param @param ossFilePath oss上的文件路径(全路径)
      * @param @param newFilePath 本地文件路径 (全路径)
      * @return void    返回类型
+     * @Title:downloadToFile
+     * @Description: 下载文件到本地
      */
-    public static void downloadToFile(String endPoint, String accessKeyId, String accessKeySecret, String bucketName, String ossFilePath, String newFilePath){
+    public static void downloadToFile(String endPoint, String accessKeyId, String accessKeySecret, String bucketName, String ossFilePath, String newFilePath) {
         //实例化OSSClient对象
         OSSClient ossClient = (OSSClient) new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
         try {
@@ -844,6 +869,115 @@ public class FileUtils {
     }
 
 
+    /**
+     * 删除文件
+     *
+     * @param url 示例:'download/file.xsl' oss服务器文件路径以及文件名
+     */
+    public static void remove(String url) {
+        try {
+            // 创建OSSClient实例。
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+            // 判断当前文件url 是否存在
+            boolean exist = ossClient.doesObjectExist(bucketName, url);
+            if (!exist) {
+                System.out.println("文件不存在");
+            } else {
+                // 删除文件。
+                ossClient.deleteObject(bucketName, url);
+                // 关闭OSSClient。
+                ossClient.shutdown();
+
+            }
+        } catch (Exception e) {
+            System.out.println(e);
+        }
+
+    }
+
+
+    /**
+     * 获取OSS连接
+     *
+     * @return
+     */
+    private static void getOSSClient() {
+        if (ossclient == null) {
+            ossclient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        }
+    }
+
+    /**
+     * 根据key删除OSS服务器上的文件
+     * <p>
+     * param ossClient oss连接
+     * param bucketName 存储空间
+     * param folder 模拟文件夹名 如"qj_nanjing/"
+     * param key Bucket下的文件的路径名+文件名 如:"upload/cake.jpg"
+     */
+    public static void deleteFile(String bucketName, String folder, String key) {
+        //获取OSS存储client
+        getOSSClient();
+        ossclient.deleteObject(bucketName, folder + key);
+        log.info("删除" + bucketName + "下的文件" + folder + key + "成功");
+    }
+
+    /**
+     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
+     * param fileName 文件名
+     * return 文件的 contentType
+     */
+    public static String getContentTypeByOSS(String fileName) {
+        // 文件的后缀名
+        String fileExtension = fileName.substring(fileName.lastIndexOf("."));
+        if (".bmp".equalsIgnoreCase(fileExtension)) {
+            return "image/bmp";
+        }
+        if (".gif".equalsIgnoreCase(fileExtension)) {
+            return "image/gif";
+        }
+        if (".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension)
+                || ".png".equalsIgnoreCase(fileExtension)) {
+            return "image/jpeg";
+        }
+        if (".png".equalsIgnoreCase(fileExtension)) {
+            return "image/png";
+        }
+        if (".html".equalsIgnoreCase(fileExtension)) {
+            return "text/html";
+        }
+        if (".txt".equalsIgnoreCase(fileExtension)) {
+            return "text/plain";
+        }
+        if (".vsd".equalsIgnoreCase(fileExtension)) {
+            return "application/vnd.visio";
+        }
+        if (".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) {
+            return "application/vnd.ms-powerpoint";
+        }
+        if (".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) {
+            return "application/msword";
+        }
+        if (".xml".equalsIgnoreCase(fileExtension)) {
+            return "text/xml";
+        }
+        // 默认返回类型
+        return null;
+    }
+
+
+    /**
+     * 下载文件,此处主要是给Controller层提供一个OSS的Object类
+     * objectName示例:download/file.xsl,()这里是oss文件列表中 文件路径和文件名
+     */
+    public static OSSObject downloadOssFile(OutputStream os, String objectName) {
+        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
+        return ossObject;
+
+    }
+
     // 测试
     public static void main(String[] args) throws FileNotFoundException {
         //阿里云OSS账号自行到阿里云官网申请