Ver Fonte

文件上传

lrf há 8 meses atrás
pai
commit
9a08811fd3

+ 5 - 0
pom.xml

@@ -24,6 +24,11 @@
       <artifactId>spring-boot-starter-test</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-configuration-processor</artifactId>
+      <optional>true</optional>
+    </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-devtools</artifactId>

+ 3 - 0
src/main/java/com/free/config/ExceptionEnum.java

@@ -6,6 +6,9 @@ package com.free.config;
 public enum ExceptionEnum {
   SERVICE_FAULT("400", "服务发生错误"), //
   VALID("4001", "参数校验失败"), // 一般只用码
+  UPLOAD_FILE_NOT_FOUND("4002", "未找到上传文件"),
+  UPLOAD_PATH_ERROR("4003", "上传文件地址解析失败"),
+  UPLOAD_FAILED("4004", "上传文件失败"),
   ACCOUNT_IS_EXIST("4002", "账号已存在"),
   ACCOUNT_NOT_FOUND("4011", "未找到账号信息"),
   PASSWORD_ERROR("4012", "密码错误"),

+ 122 - 0
src/main/java/com/free/controller/ChatRecordController.java

@@ -0,0 +1,122 @@
+package com.free.controller;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.validation.Valid;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.free.config.CustomizationException;
+import com.free.config.ExceptionEnum;
+import com.free.config.ResponseFormat;
+import com.free.entity.ChatRecord;
+import com.free.service.ChatRecordService;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@RestController
+@RequestMapping("/chatRecord")
+@Api(tags = "对话记录")
+public class ChatRecordController {
+  @Autowired
+  private ChatRecordService service;
+
+  /** 创建数据 */
+  @ApiOperation("创建数据")
+  @PostMapping("")
+  public Object save(@RequestBody @Valid ChatRecord data) {
+    this.service.save(data);
+    QueryWrapper qw = new QueryWrapper<>();
+    qw.eq("id", data.getId());
+    Map returnData = this.service.getMap(qw);
+    return ResponseFormat.success(returnData);
+    // return ResponseFormat.success();
+  }
+
+  /** 修改数据 */
+  @ApiOperation("修改数据")
+  @PostMapping("/{id}")
+  public Object update(@PathVariable long id, @RequestBody ChatRecord data) {
+    QueryWrapper qw = new QueryWrapper<>();
+    qw.eq("id", id);
+    Long num = this.service.count(qw);
+    if (num <= 0) {
+      throw new CustomizationException(ExceptionEnum.NOT_FOUND);
+    }
+    data.setId(id);
+    this.service.updateById(data);
+    Object newData = this.service.getById(id);
+    return ResponseFormat.success(newData);
+  }
+
+  /** 列表查询 */
+  @ApiOperation("查询数据列表")
+  @SuppressWarnings({ "unchecked" })
+  @GetMapping()
+  public Object list(@RequestParam Map<String, Object> allParams) {
+    Long skip = null, limit = null;
+    Map map = new HashMap();
+    QueryWrapper qw = new QueryWrapper<>();
+    /** 参数处理处理 */
+    for (String key : allParams.keySet()) {
+      Object value = allParams.get(key);
+      if (key.equals("skip")) {
+        skip = Long.valueOf(String.valueOf(value));
+      } else if (key.equals("limit")) {
+        limit = Long.valueOf(String.valueOf(value));
+      } else {
+        // 其他为查询条件
+        qw.eq(key, value);
+      }
+    }
+    /** 分页处理 */
+    if (null != skip && null != limit) {
+      IPage page = new Page<>(skip, limit);
+      IPage pageResult = service.page(page, qw);
+      List data = pageResult.getRecords();
+      long total = pageResult.getTotal();
+      map.put("data", data);
+      map.put("total", total);
+    } else {
+      List list = service.list(qw);
+      map.put("data", list);
+    }
+    return ResponseFormat.success(map);
+  }
+
+  /** 根据id查询 */
+  @ApiOperation("查询数据")
+  @GetMapping("/{id}")
+  public Object fetch(@PathVariable long id) {
+    Object newData = service.getById(id);
+    return ResponseFormat.success(newData);
+  }
+
+  /** 根据id删除数据 */
+  @ApiOperation("删除数据")
+  @DeleteMapping("/{id}")
+  public Object delete(@PathVariable long id) {
+    QueryWrapper qw = new QueryWrapper<>();
+    qw.eq("id", id);
+    Long num = service.count(qw);
+    if (num <= 0) {
+      throw new CustomizationException(ExceptionEnum.NOT_FOUND);
+    }
+    service.removeById(id);
+    return ResponseFormat.success();
+  }
+}

+ 188 - 0
src/main/java/com/free/controller/FileController.java

@@ -0,0 +1,188 @@
+package com.free.controller;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.MediaTypeFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.free.annotation.PassToken;
+import com.free.config.CustomizationException;
+import com.free.config.ExceptionEnum;
+import com.free.config.ResponseFormat;
+
+import io.swagger.annotations.ApiOperation;
+
+@RestController
+@RequestMapping("/files")
+public class FileController {
+  @Value("${spring.servlet.multipart.location}")
+  private String baseDir;
+  /** 全局路由前缀 */
+  @Value("${server.servlet.context-path}")
+  private String ContextPath;
+  /** 文件路由前缀 */
+  private String filePrefix = "/files";
+
+  /** 虚拟路径前缀 */
+  private String virtualFilePrefix() {
+    return this.ContextPath + filePrefix;
+  };
+
+  @PassToken
+  @ApiOperation("读取文件")
+  @GetMapping("/**")
+  public Object readFile() throws FileNotFoundException {
+    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+    String virtualPath = request.getServletPath();
+    // 除去虚拟路径前缀
+    virtualPath = virtualPath.replace(virtualFilePrefix(), "");
+    String realPath = Paths.get(baseDir, virtualPath).toString();
+    File file = new File(realPath);
+    Optional<MediaType> mediaType = MediaTypeFactory.getMediaType(realPath);
+    System.out.println(mediaType);
+    InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
+    HttpHeaders headers = new HttpHeaders();
+    headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
+    headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
+    headers.add("Pragma", "no-cache");
+    headers.add("Expires", "0");
+    headers.setContentType(mediaType.get());
+    ResponseEntity<Object> responseEntity = ResponseEntity.ok().headers(headers).contentLength(
+        file.length()).body(resource);
+
+    return responseEntity;
+  }
+
+  @PassToken
+  @ApiOperation("上传")
+  @PostMapping("/**/upload")
+  public Object upload(@RequestParam("file") MultipartFile file) {
+    if (file == null || file.isEmpty()) {
+      throw new CustomizationException(ExceptionEnum.UPLOAD_FILE_NOT_FOUND);
+    }
+    Map<String, String> map = this.checkDir();
+    System.out.println(map);
+    String fileName = map.get("fileName");
+    if (!StringUtils.hasText(fileName)) {
+      fileName = Long.toString(System.currentTimeMillis());
+    }
+    try {
+      String uploadDir = map.get("realPath");
+      String ext = getFileExt(file.getOriginalFilename());
+      fileName = fileName + "." + ext;
+      String sep = File.separator;
+      String filePath = uploadDir + sep + fileName;
+      File uploadedFile = new File(filePath);
+      file.transferTo(uploadedFile);
+    } catch (IOException e) {
+      e.printStackTrace();
+      throw new CustomizationException(ExceptionEnum.UPLOAD_FAILED);
+    }
+    Map<String, String> returnData = new HashMap<>();
+    String uri = map.get("virtualPath") + "/" + fileName;
+    String id = String.valueOf(UUID.randomUUID());
+    returnData.put("uri", uri);
+    returnData.put("id", id);
+    return ResponseFormat.success(returnData);
+  }
+
+  private String getFileExt(String name) {
+    int lastIndex = name.lastIndexOf(".");
+    String ext = null;
+    if (lastIndex > 0) {
+      ext = name.substring(lastIndex + 1);
+    }
+    return ext;
+  }
+
+  /** 根据请求路径,创建文件夹,返回真实路径(不包含文件名),虚拟路径(返回前端用,不包含文件名),文件名(可能没有) */
+  private Map<String, String> checkDir() {
+    Map<String, String> map = new HashMap<>();
+    ArrayList<String> fullPathList = new ArrayList<>();
+    String fileName = null;
+    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+    try {
+      String methodPath = request.getRequestURI();
+      // 过滤掉头部的/files和尾部upload
+      methodPath = methodPath.replace(virtualFilePrefix(), "").replace("/upload", "");
+      // 按"/"分割,最后一个为文件名其余的为路径
+      String[] dirPaths = methodPath.split("/");
+      ArrayList<String> dirList = new ArrayList<>(Arrays.asList(dirPaths));
+      // 删除第一项,一定是空字符串("")
+      dirList.remove(0);
+      if (dirList.size() <= 0) {
+        // 如果移出第一项后,list里没有值了.那这个地址肯定有问题,抛异常触发catch的异常就行
+        throw new Exception();
+      }
+      // 接下来解析具体文件路径,List 第一项是project; 第二项是 catalog; 第三项是 item
+      // 字符串中间出现 "_"则说明再建新文件夹
+      for (int i = 0; i < dirList.size(); i++) {
+        String name = dirList.get(i);
+        if (i == 0) {
+          // project 不需要解析,写成什么样就直接创建文件夹
+          fullPathList.add(name);
+        } else if (i == 1) {
+          // catalog需要解析
+          String[] catalogPaths = name.split("_");
+          ArrayList<String> catalogList = new ArrayList<>(Arrays.asList(catalogPaths));
+          fullPathList.addAll(catalogList);
+        } else if (i == 2) {
+          // item是规定的fileName
+          fileName = name;
+        }
+      }
+    } catch (Exception e) {
+      throw new CustomizationException(ExceptionEnum.UPLOAD_PATH_ERROR);
+    }
+    String fullPath = baseDir;
+    StringBuffer virtualPathBuffer = new StringBuffer(virtualFilePrefix());
+    File baseDirFile = new File(fullPath);
+    if (!baseDirFile.exists()) {
+      baseDirFile.mkdir();
+    }
+    // 检查是否有文件夹,没有文件夹需要创建
+    for (String path : fullPathList) {
+      Path fp = Paths.get(fullPath, path);
+      fullPath = fp.toString();
+      File file = new File(fullPath);
+      if (!file.exists()) {
+        file.mkdir();
+      }
+      virtualPathBuffer.append("/" + path);
+    }
+    map.put("realPath", fullPath);
+    map.put("virtualPath", virtualPathBuffer.toString());
+    map.put("fileName", fileName);
+    return map;
+  }
+}

+ 16 - 0
src/main/java/com/free/controller/system/AdminController.java

@@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.free.annotation.PassToken;
 import com.free.config.CustomizationException;
 import com.free.config.ExceptionEnum;
 import com.free.config.ResponseFormat;
@@ -139,4 +140,19 @@ public class AdminController {
     service.removeById(id);
     return ResponseFormat.success();
   }
+
+  @PassToken
+  @PostMapping("/initData")
+  public Object initSuperAdmin() {
+      Admin admin = new Admin();
+      admin.setAccount("sadmin");
+      admin.setIs_super("0");
+      admin.setNick_name("超级管理员");
+      String pwd = "1qaz2wsx";
+      String cpwd = BcryptUtil.encryptPassword(pwd);
+      admin.setPassword(cpwd);
+      this.service.save(admin);
+      return ResponseFormat.success();
+  }
+  
 }

+ 36 - 0
src/main/java/com/free/entity/ChatRecord.java

@@ -0,0 +1,36 @@
+package com.free.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.free.utils.BaseEntity;
+import com.gitee.sunchenbin.mybatis.actable.annotation.Column;
+import com.gitee.sunchenbin.mybatis.actable.annotation.Table;
+import com.gitee.sunchenbin.mybatis.actable.constants.MySqlTypeConstant;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Table(name = "chatRecord")
+@TableName(value = "chatRecord")
+@ApiModel("对话记录")
+public class ChatRecord extends BaseEntity {
+  @Column(comment = "客服人员id")
+  @TableField(value = "customer_id")
+  @ApiModelProperty("客服人员id")
+  private Long customer_id;
+  
+  @Column(comment = "用户id")
+  @TableField(value = "user_id")
+  @ApiModelProperty("用户id")
+  private Long user_id;
+
+  @Column(comment = "对话内容", type = MySqlTypeConstant.TEXT)
+  @TableField(value = "content")
+  @ApiModelProperty("对话内容")
+  private String content;
+
+}

+ 36 - 0
src/main/java/com/free/entity/Question.java

@@ -0,0 +1,36 @@
+package com.free.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.free.utils.BaseEntity;
+import com.gitee.sunchenbin.mybatis.actable.annotation.Column;
+import com.gitee.sunchenbin.mybatis.actable.annotation.Table;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Table(name = "question")
+@TableName(value = "question")
+@ApiModel("预设问题")
+public class Question extends BaseEntity{
+  @Column(comment = "标题")
+  @TableField(value = "title")
+  @ApiModelProperty("标题")
+  private String title;
+
+  @Column(comment = "答案")
+  @TableField(value = "answer")
+  @ApiModelProperty("答案")
+  private String answer;
+
+
+  @Column(comment = "所属平台")
+  @TableField(value = "platform")
+  @ApiModelProperty("所属平台")
+  private String platform;
+  
+}

+ 11 - 0
src/main/java/com/free/mapper/ChatRecordMapper.java

@@ -0,0 +1,11 @@
+package com.free.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import com.free.entity.ChatRecord;
+
+@Mapper
+public interface ChatRecordMapper extends BaseMapper<ChatRecord> {
+
+}

+ 12 - 0
src/main/java/com/free/service/ChatRecordService.java

@@ -0,0 +1,12 @@
+package com.free.service;
+
+import org.springframework.stereotype.Service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.free.entity.ChatRecord;
+import com.free.mapper.ChatRecordMapper;
+
+@Service
+public class ChatRecordService extends ServiceImpl<ChatRecordMapper, ChatRecord> {
+
+}

+ 0 - 3
src/main/java/com/free/utils/JwtUtil.java

@@ -1,6 +1,5 @@
 package com.free.utils;
 
-import com.auth0.jwt.JWTVerifier;
 import com.auth0.jwt.algorithms.Algorithm;
 import com.auth0.jwt.interfaces.Claim;
 import com.auth0.jwt.interfaces.DecodedJWT;
@@ -9,7 +8,6 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.free.config.CustomizationException;
 import com.free.config.ExceptionEnum;
 import com.free.entity.system.LoginRecord;
-import com.free.mapper.system.LoginRecordMapper;
 import com.free.service.system.LoginRecordService;
 import com.auth0.jwt.JWT;
 import com.auth0.jwt.JWTCreator;
@@ -24,7 +22,6 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 

+ 10 - 3
src/main/resources/application.yml

@@ -2,8 +2,18 @@ server:
   port: 4001
   servlet:
     context-path: /customer/api
+    register-default-servlet: true
 
 spring:
+  mvc:
+    pathmatch:
+      matching-strategy: ant_path_matcher
+  servlet:
+    multipart:
+      enabled: true
+      max-file-size: 100MB
+      max-request-size: 1000MB
+      location: D:/temp/customerUpload/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://192.168.1.153:3306/customer?serverTimezone=GMT%2B8
@@ -18,9 +28,6 @@ spring:
   devtools:
     restart:
       enabled: true
-  mvc:
-    pathmatch:
-      matching-strategy: ANT_PATH_MATCHER
   autoconfigure:
     exclude: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
   jackson: