From 3321d513cbab14a70d0123708f1352d61456966e Mon Sep 17 00:00:00 2001
From: cjl <276999030@qq.com>
Date: Fri, 22 Sep 2023 10:57:04 +0800
Subject: [PATCH] feat:添加附件功能

---
 screen-api/src/main/java/com/moral/api/controller/FileTableController.java    |   62 +
 screen-api/src/main/java/com/moral/api/service/FileTableService.java          |   29 
 screen-api/src/main/java/com/moral/api/mapper/FileTableMapper.java            |   16 
 screen-api/src/main/java/com/moral/api/pojo/vo/file/FileVo.java               |   26 
 screen-api/pom.xml                                                            |    5 
 screen-api/src/main/java/com/moral/api/pojo/vo/user/QxUser.java               |   30 
 screen-api/src/main/resources/application-dev.yml                             |    6 
 screen-api/src/main/java/com/moral/api/utils/FileTypeUtils.java               |  126 +++
 screen-api/src/main/java/com/moral/api/service/impl/FileTableServiceImpl.java |  188 +++++
 screen-api/src/main/resources/mapper/FileTableMapper.xml                      |   20 
 screen-api/src/main/java/com/moral/api/config/Interceptor/UserHelper.java     |   49 +
 screen-api/src/main/java/com/moral/api/utils/StringUtils.java                 | 1175 ++++++++++++++++++++++++++++++++++++
 screen-api/src/main/resources/application-qa.yml                              |    4 
 screen-api/src/main/java/com/moral/api/pojo/enums/FileType.java               |   69 ++
 screen-api/src/main/java/com/moral/api/entity/FileTable.java                  |   92 ++
 15 files changed, 1,894 insertions(+), 3 deletions(-)

diff --git a/screen-api/pom.xml b/screen-api/pom.xml
index c9bd01d..6f45409 100644
--- a/screen-api/pom.xml
+++ b/screen-api/pom.xml
@@ -68,6 +68,11 @@
             <version>1.5.0</version>
         </dependency>
         <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.8</version>
+        </dependency>
+        <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
             <version>5.3.0</version>
diff --git a/screen-api/src/main/java/com/moral/api/config/Interceptor/UserHelper.java b/screen-api/src/main/java/com/moral/api/config/Interceptor/UserHelper.java
new file mode 100644
index 0000000..4c6a53d
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/config/Interceptor/UserHelper.java
@@ -0,0 +1,49 @@
+package com.moral.api.config.Interceptor;
+
+import com.alibaba.fastjson.JSON;
+import com.moral.api.pojo.vo.user.QxUser;
+import com.moral.api.utils.BeanConverts;
+import com.moral.api.utils.StringUtils;
+import com.moral.constant.ResponseCodeEnum;
+import com.moral.exception.TokenException;
+import com.moral.util.TokenUtils;
+import net.sf.cglib.beans.BeanMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @ClassName UserHelper
+ * @Description TODO
+ * @Author @cjl
+ * @Date 2023-09-21 15:47
+ * @Version 1.0
+ */
+
+public class UserHelper {
+    public static QxUser getCurrentUser(){
+        Map<String, Object> userInfo = new HashMap<>();
+        try {
+             userInfo = (Map<String, Object>) TokenUtils.getUserInfo();
+        }catch (Exception e){
+        }
+        if (Objects.isNull(userInfo)||Objects.isNull(userInfo.get("userId"))) {
+            return null;
+        }
+        try {
+            String s = JSON.toJSONString(userInfo);
+            return JSON.parseObject(s, QxUser.class);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
diff --git a/screen-api/src/main/java/com/moral/api/controller/FileTableController.java b/screen-api/src/main/java/com/moral/api/controller/FileTableController.java
new file mode 100644
index 0000000..9a4cb00
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/controller/FileTableController.java
@@ -0,0 +1,62 @@
+package com.moral.api.controller;
+
+
+import com.moral.api.pojo.vo.file.FileVo;
+import com.moral.api.service.FileTableService;
+import com.moral.constant.ResultMessage;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.web.bind.annotation.*;
+
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * <p>
+ * ��������� ���������������
+ * </p>
+ *
+ * @author moral
+ * @since 2023-09-21
+ */
+@RestController
+@RequestMapping("/file")
+public class FileTableController {
+
+    private final FileTableService fileTableService;
+
+    public FileTableController(FileTableService fileTableService) {
+        this.fileTableService = fileTableService;
+    }
+
+
+    @PostMapping("/upload")
+    @ApiOperation("������������")
+    public ResultMessage<FileVo> upload(@RequestParam("file") @ApiParam(name = "file", value = "������������") MultipartFile file,
+                                        @RequestParam("sysCode") @ApiParam(name = "sysCode", value = "������������") Integer sysCode){
+        return ResultMessage.ok(fileTableService.upload(file,sysCode));
+    }
+
+    @PostMapping("/multipleUpload")
+    @ApiOperation("���������������������")
+    public ResultMessage<List<FileVo>> upload(@RequestParam("file") @ApiParam(name = "file", value = "������������") List<MultipartFile> file,
+                                              @RequestParam("sysCode") @ApiParam(name = "sysCode", value = "������������") Integer sysCode){
+        return ResultMessage.ok(fileTableService.upload(file,sysCode));
+    }
+
+    @GetMapping("/preview/{id}")
+    @ApiOperation("������������")
+    public void preview(@PathVariable("id") Integer id, HttpServletRequest request, HttpServletResponse response) {
+        fileTableService.preview(id, request, response);
+    }
+
+    @GetMapping("/preview/cover/{id}")
+    @ApiOperation("������������������")
+    public void coverPreview(@PathVariable("id") Integer id, HttpServletRequest request, HttpServletResponse response) {
+        fileTableService.coverPreview(id, request, response);
+    }
+
+}
diff --git a/screen-api/src/main/java/com/moral/api/entity/FileTable.java b/screen-api/src/main/java/com/moral/api/entity/FileTable.java
new file mode 100644
index 0000000..8d27836
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/entity/FileTable.java
@@ -0,0 +1,92 @@
+package com.moral.api.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * ���������
+ * </p>
+ *
+ * @author moral
+ * @since 2023-09-21
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+public class FileTable extends Model<FileTable> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ������id
+     */
+    @TableId(value = "file_id", type = IdType.AUTO)
+    private Integer fileId;
+
+    /**
+     * ������
+     */
+    private Integer fileModule;
+
+    /**
+     * ������������id
+     */
+    private Integer relationId;
+
+    /**
+     * ������������
+     */
+    private String fileName;
+
+    /**
+     * ������������1������2������
+     */
+    private Integer fileType;
+
+    /**
+     * ������������������
+     */
+    private String fileAddress;
+
+    /**
+     * ������������
+     */
+    private Integer fileSize;
+
+    /**
+     * ������������
+     */
+    private Integer isDel;
+
+    /**
+     * ���������id
+     */
+    private Integer createId;
+
+    /**
+     * ���������������
+     */
+    private String createName;
+
+    /**
+     * ������������
+     */
+    private Date createTime;
+
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.fileId;
+    }
+
+}
diff --git a/screen-api/src/main/java/com/moral/api/mapper/FileTableMapper.java b/screen-api/src/main/java/com/moral/api/mapper/FileTableMapper.java
new file mode 100644
index 0000000..6486afb
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/mapper/FileTableMapper.java
@@ -0,0 +1,16 @@
+package com.moral.api.mapper;
+
+import com.moral.api.entity.FileTable;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * ��������� Mapper ������
+ * </p>
+ *
+ * @author moral
+ * @since 2023-09-21
+ */
+public interface FileTableMapper extends BaseMapper<FileTable> {
+
+}
diff --git a/screen-api/src/main/java/com/moral/api/pojo/enums/FileType.java b/screen-api/src/main/java/com/moral/api/pojo/enums/FileType.java
new file mode 100644
index 0000000..c90a951
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/pojo/enums/FileType.java
@@ -0,0 +1,69 @@
+package com.moral.api.pojo.enums;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import lombok.Getter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @ClassName FileType
+ * @Description
+ * @Author fan
+ * @Date 2021/2/1 13:48
+ * @Version 1.0
+ **/
+@Getter
+public enum FileType {
+
+    /**
+     * ������
+     */
+    NON(-1),
+    /**
+     * ������
+     */
+    PICTURE(1),
+    /**
+     * word
+     */
+    WORD(2),
+    /**
+     * excel
+     */
+    EXCEL(3),
+    /**
+     * pdf
+     */
+    PDF(4),
+    /**
+     * ���������
+     */
+    ZIP(5),
+    ;
+
+    @EnumValue
+    private final Integer value;
+
+    FileType(Integer value) {
+        this.value = value;
+    }
+
+    private static final Map<Integer, FileType> VALUE_MAP = new HashMap<>();
+
+    static {
+        for (FileType var : values()) {
+            VALUE_MAP.put(var.getValue(), var);
+        }
+    }
+
+    @JsonCreator
+    public static FileType getEnumByCode(Integer value) {
+        FileType fileType = VALUE_MAP.get(value);
+        if (fileType == null) {
+            throw new RuntimeException("enum not find element, [" + value + "]");
+        }
+        return fileType;
+    }
+}
diff --git a/screen-api/src/main/java/com/moral/api/pojo/vo/file/FileVo.java b/screen-api/src/main/java/com/moral/api/pojo/vo/file/FileVo.java
new file mode 100644
index 0000000..4eb29dd
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/pojo/vo/file/FileVo.java
@@ -0,0 +1,26 @@
+package com.moral.api.pojo.vo.file;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * @ClassName FileVo
+ * @Description TODO
+ * @Author @cjl
+ * @Date 2023-09-21 14:51
+ * @Version 1.0
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(description="FileVo - ������VO������")
+public class FileVo {
+    @ApiModelProperty(value = "ID")
+    private Integer fileId;
+
+    @ApiModelProperty(value = "������������")
+    private String fileName;
+}
diff --git a/screen-api/src/main/java/com/moral/api/pojo/vo/user/QxUser.java b/screen-api/src/main/java/com/moral/api/pojo/vo/user/QxUser.java
new file mode 100644
index 0000000..95e8336
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/pojo/vo/user/QxUser.java
@@ -0,0 +1,30 @@
+package com.moral.api.pojo.vo.user;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @ClassName QxUser
+ * @Description TODO
+ * @Author @cjl
+ * @Date 2023-09-21 15:59
+ * @Version 1.0
+ */
+@Data
+@Accessors(chain = true)
+public class QxUser {
+    /**
+     * ������id
+     */
+    private Integer userId;
+
+    /**
+     * ������������
+     */
+    private String userName;
+
+    /**
+     * ������
+     */
+    private String account;
+}
diff --git a/screen-api/src/main/java/com/moral/api/service/FileTableService.java b/screen-api/src/main/java/com/moral/api/service/FileTableService.java
new file mode 100644
index 0000000..f37594d
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/service/FileTableService.java
@@ -0,0 +1,29 @@
+package com.moral.api.service;
+
+import com.moral.api.entity.FileTable;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.moral.api.pojo.vo.file.FileVo;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * <p>
+ * ��������� ���������
+ * </p>
+ *
+ * @author moral
+ * @since 2023-09-21
+ */
+public interface FileTableService extends IService<FileTable> {
+
+    FileVo upload(MultipartFile file, Integer sysCode);
+
+    List<FileVo> upload(List<MultipartFile>files,Integer sysCode);
+
+    void preview(Integer id, HttpServletRequest request, HttpServletResponse response);
+
+    void coverPreview(Integer id, HttpServletRequest request, HttpServletResponse response);
+}
diff --git a/screen-api/src/main/java/com/moral/api/service/impl/FileTableServiceImpl.java b/screen-api/src/main/java/com/moral/api/service/impl/FileTableServiceImpl.java
new file mode 100644
index 0000000..63915c5
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/service/impl/FileTableServiceImpl.java
@@ -0,0 +1,188 @@
+package com.moral.api.service.impl;
+
+import com.moral.api.config.Interceptor.UserHelper;
+import com.moral.api.entity.FileTable;
+import com.moral.api.exception.BusinessException;
+import com.moral.api.mapper.FileTableMapper;
+import com.moral.api.pojo.enums.FileType;
+import com.moral.api.pojo.vo.file.FileVo;
+import com.moral.api.pojo.vo.user.QxUser;
+import com.moral.api.service.FileTableService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.moral.api.utils.FileTypeUtils;
+import com.moral.api.utils.StringUtils;
+import com.moral.util.DateUtils;
+import lombok.extern.slf4j.Slf4j;
+import net.coobird.thumbnailator.Thumbnails;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.*;
+
+/**
+ * <p>
+ * ��������� ���������������
+ * </p>
+ *
+ * @author moral
+ * @since 2023-09-21
+ */
+@Service
+@Slf4j
+public class FileTableServiceImpl extends ServiceImpl<FileTableMapper, FileTable> implements FileTableService {
+    @Value("${file.path}")
+    private String basePath;
+    @Override
+    public FileVo upload(MultipartFile file, Integer sysCode) {
+        String originalFilename = file.getOriginalFilename().replaceAll(StringUtils.SPACE, StringUtils.EMPTY).toLowerCase();
+        String suffix = originalFilename.substring(originalFilename.lastIndexOf(StringUtils.DOT));
+        FileType fileType = FileTypeUtils.getFileType(suffix.toLowerCase());
+        // ������������������������  ������������ + ������������ + ������
+        String filePath = getFilePath(sysCode.toString());
+        // ������������
+        String targetFolder = basePath.replaceAll(StringUtils.BACKSLASH.concat(StringUtils.BACKSLASH), StringUtils.SLASH).concat(StringUtils.SLASH).concat(filePath);
+        //������uuid ������������������������������������
+        String storageFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf(StringUtils.DOT));
+        storageFile(file, storageFileName, targetFolder);
+
+        // ������������������
+        QxUser user = UserHelper.getCurrentUser();
+        FileTable sysFile = new FileTable();
+        sysFile.setFileName(originalFilename).setFileType(fileType.getValue()).setFileSize((int) file.getSize()).setFileAddress(filePath.concat(storageFileName))
+                .setFileModule(sysCode).setCreateTime(new Date());
+        if (Objects.nonNull(user)) {
+            sysFile.setCreateId(user.getUserId()).setCreateName(user.getUserName());
+        }
+        save(sysFile);
+        return new FileVo().setFileId(sysFile.getFileId()).setFileName(originalFilename);
+    }
+
+    @Override
+    public List<FileVo> upload(List<MultipartFile> files, Integer sysCode) {
+        List<FileVo> fileList = new LinkedList<>();
+        for (MultipartFile file : files) {
+            fileList.add(upload(file, sysCode));
+        }
+        return fileList;
+    }
+
+    @Override
+    public void preview(Integer id, HttpServletRequest request, HttpServletResponse response) {
+        FileTable sysFile = getById(id);
+        File file = new File(handleFileRealPath(sysFile.getFileAddress()));
+        String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT));
+        if (FileTypeUtils.SUFFIX_MP4.equals(suffix)) {
+            videoPreview(file, request, response);
+        } else {
+            try (OutputStream out = response.getOutputStream(); InputStream in = new FileInputStream(file)) {
+                response.setContentType(FileTypeUtils.convertHeaderType(suffix));
+                response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(sysFile.getFileName(), "UTF-8"));
+                int len;
+                // ���������������������
+                byte[] buffer = new byte[1024];
+                while ((len = in.read(buffer)) > 0) {
+                    out.write(buffer, 0, len);
+                }
+            } catch (Exception e) {
+                log.error("������������������!!! e={}", e.getMessage());
+            }
+        }
+    }
+
+    private String getFilePath(String sysCode) {
+        return sysCode.concat(StringUtils.SLASH).concat(StringUtils.SLASH).concat(DateUtils.dateToDateString(new Date(),DateUtils.yyyyMMdd_EN)).concat(StringUtils.SLASH);
+    }
+
+    public void storageFile(MultipartFile file, String originalFilename, String targetFolder) {
+        File f = new File(targetFolder, originalFilename);
+        try {
+            // ������������
+            if (!f.getParentFile().exists()) {
+                if (!f.getParentFile().mkdirs()) {
+                    log.error("error:������������������! dir={}", f.getAbsolutePath());
+                }
+            }
+            file.transferTo(f);
+        } catch (IOException e) {
+            log.error("error:������������������!!!e={}", e.getMessage());
+            throw new BusinessException("������������������������������!");
+        }
+    }
+    private String handleFileRealPath(String path) {
+        return basePath.replaceAll(StringUtils.BACKSLASH.concat(StringUtils.BACKSLASH), StringUtils.SLASH).concat(StringUtils.SLASH).concat(path);
+    }
+    private void videoPreview(File file, HttpServletRequest request, HttpServletResponse response) {
+        String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT));
+        //������������
+        response.setContentType(FileTypeUtils.convertHeaderType(suffix));
+        response.setHeader("Accept-Ranges", "bytes");
+        response.setHeader("ETag", file.getName());
+        response.setHeader("Last-Modified", new Date().toString());
+        long contentLength = file.length();
+
+        //���������������������������������������������������������������
+        long length = Math.min(contentLength, 1024);
+        long start = 0, end = 0;
+        String range = request.getHeader("Range");
+        //������������������������content length���������������������������������������
+        if (range == null) {
+            response.setHeader("Content-length", contentLength + "");
+        } else {
+            //������������������������������������������������������������
+            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//206
+
+            if (range.startsWith("bytes=")) {
+                String[] values = range.split("=")[1].split("-");
+                start = Integer.parseInt(values[0]);
+                if (values.length > 1) {
+                    end = Integer.parseInt(values[1]);
+                }
+            }
+            //���end,���������������������������
+            long maxSize = 1024 * 1024; //1MB
+            if (end > 0) {
+                length = end - start + 1;
+                response.setHeader("Content-length", "" + length);
+                response.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + contentLength);
+            } else {
+                length = Math.min((contentLength - start), maxSize);
+                response.setHeader("Content-length", "" + length);
+                response.setHeader("Content-Range", "bytes " + start + "-" + (start + length - 1) + "/" + contentLength);
+            }
+        }
+        try {
+            FileInputStream fileInputStream = new FileInputStream(file);
+            OutputStream out = response.getOutputStream();
+            //������������������������byte[]���������
+            byte[] data = new byte[(int) length];
+            fileInputStream.skip(start);
+            fileInputStream.read(data);
+            //������������������������������������
+            out.write(data);
+            out.close();
+            fileInputStream.close();
+        } catch (Exception e) {
+            log.error("������������������!!! e={}", e.getMessage());
+        }
+    }
+    @Override
+    public void coverPreview(Integer id, HttpServletRequest request, HttpServletResponse response) {
+        FileTable sysFile = getById(id);
+
+        File file = new File(handleFileRealPath(sysFile.getFileAddress()));
+        String suffix = file.getName().substring(file.getName().lastIndexOf(StringUtils.DOT));
+
+        try (OutputStream out = response.getOutputStream()) {
+            response.setContentType(FileTypeUtils.convertHeaderType(suffix));
+            response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(sysFile.getFileName(), "UTF-8"));
+            Thumbnails.of(file).size(420, 200).toOutputStream(out);
+        } catch (Exception e) {
+            log.error("������������������!!! e={}", e.getMessage());
+        }
+    }
+}
diff --git a/screen-api/src/main/java/com/moral/api/utils/FileTypeUtils.java b/screen-api/src/main/java/com/moral/api/utils/FileTypeUtils.java
new file mode 100644
index 0000000..7096afb
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/utils/FileTypeUtils.java
@@ -0,0 +1,126 @@
+package com.moral.api.utils;
+
+import com.moral.api.pojo.enums.FileType;
+
+/**
+ * @ClassName: FileTypeUtils
+ * @Description:
+ * @Author: fan
+ * @Date: 2021/2/1 13:41
+ * @Version: 1.0
+ **/
+public class FileTypeUtils {
+    /**
+     * ������������
+     */
+    private static final String SUFFIX_JPE = ".jpe";
+    private static final String SUFFIX_JPG = ".jpg";
+    private static final String SUFFIX_PNG = ".png";
+    private static final String SUFFIX_JPEG = ".jpeg";
+    private static final String SUFFIX_BMP = ".bmp";
+    private static final String SUFFIX_GIF = ".gif";
+
+    /**
+     * word
+     */
+    public static final String SUFFIX_DOC = ".doc";
+    public static final String SUFFIX_DOCX = ".docx";
+
+    /**
+     * excel
+     */
+    private static final String SUFFIX_XLSX = ".xlsx";
+    private static final String SUFFIX_XLS = ".xls";
+
+    /**
+     * pdf
+     */
+    public static final String SUFFIX_PDF = ".pdf";
+
+    /**
+     * ���������
+     */
+    private static final String SUFFIX_ZIP = ".zip";
+    private static final String SUFFIX_RAR = ".rar";
+    private static final String SUFFIX_JAR = ".jar";
+    private static final String SUFFIX_GZIP = ".gzip";
+
+    private static final String SUFFIX_TXT = ".txt";
+
+    /**
+     * ppt
+     */
+    public static final String SUFFIX_PPT = ".ppt";
+    public static final String SUFFIX_PPTX = ".pptx";
+
+
+    public static final String SUFFIX_MP4 = ".mp4";
+
+    /**
+     * @Description ������������������
+     * @author fanhq
+     * @date 2020/4/20 15:35
+     * @param suffix
+     * @return java.lang.Integer   1. ������  * 2. word  * 3. excel * 4. pdf  * 5. ���������
+     */
+    public static FileType getFileType(String suffix) {
+        switch (suffix) {
+            case SUFFIX_JPE:
+            case SUFFIX_JPG:
+            case SUFFIX_PNG:
+            case SUFFIX_JPEG:
+            case SUFFIX_BMP:
+                return FileType.PICTURE;
+            case SUFFIX_DOC:
+            case SUFFIX_DOCX:
+                return FileType.WORD;
+            case SUFFIX_XLSX:
+            case SUFFIX_XLS:
+                return FileType.EXCEL;
+            case SUFFIX_PDF:
+                return FileType.PDF;
+            case SUFFIX_ZIP:
+            case SUFFIX_RAR:
+            case SUFFIX_JAR:
+                return FileType.ZIP;
+            default:
+                return FileType.NON;
+        }
+    }
+
+    /**
+     * ���������������������������������������
+     * @param type
+     * @return
+     */
+    public static String convertHeaderType(String type) {
+        switch (type){
+            case SUFFIX_JPE:
+            case SUFFIX_JPG:
+            case SUFFIX_JPEG:
+                return "image/jpeg";
+            case SUFFIX_PNG:
+                return "image/png";
+            case SUFFIX_GIF:
+                return "image/gif";
+            case SUFFIX_ZIP:
+                return "application/zip";
+            case SUFFIX_GZIP:
+                return "application/gzip";
+            case SUFFIX_DOC:
+            case SUFFIX_DOCX:
+                return "application/msword";
+            case SUFFIX_XLSX:
+            case SUFFIX_XLS:
+                return "application/x-xls";
+            case SUFFIX_PDF:
+                return "application/pdf";
+            case SUFFIX_TXT:
+                return "text/plain";
+            case SUFFIX_MP4:
+                return "video/mp4";
+            default:
+                return "application/octet-stream";
+        }
+    }
+}
diff --git a/screen-api/src/main/java/com/moral/api/utils/StringUtils.java b/screen-api/src/main/java/com/moral/api/utils/StringUtils.java
new file mode 100644
index 0000000..bd85023
--- /dev/null
+++ b/screen-api/src/main/java/com/moral/api/utils/StringUtils.java
@@ -0,0 +1,1175 @@
+package com.moral.api.utils;
+
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/***
+ * @Author JI
+ * @Date 2020/3/27 13:44
+ * @Param
+ * @return
+ **/
+public class StringUtils extends org.apache.commons.lang3.StringUtils {
+
+    public static final String SPACE = " ";
+    public static final String DOT = ".";
+    public static final String PERIOD = "���";
+    public static final String SLASH = "/";
+    public static final String BACKSLASH = "\\";
+    public static final String EMPTY = "";
+    public static final String CRLF = "\r\n";
+    public static final String NEWLINE = "\n";
+    public static final String UNDERLINE = "_";
+    public static final String COMMA = ",";
+    public static final String COMMA_CN = "���";
+    public static final String CONNECTION_LINE = "-";
+    public static final String SEMICOLON = ";";
+    public static final String SEMICOLON_CN = "���";
+
+    public static final String HTML_NBSP = "&nbsp;";
+    public static final String HTML_AMP = "&amp";
+    public static final String HTML_QUOTE = "&quot;";
+    public static final String HTML_LT = "&lt;";
+    public static final String HTML_GT = "&gt;";
+    public static final String PLACEHOLDER = "%s";
+    public static final String FILE_SEPARATOR = System.getProperties().getProperty("file.separator");
+    public static final String EMPTY_JSON = "{}";
+
+
+    /***
+     * @Author JI
+     * @Description //������������������������������������
+     * @Date 2020/3/27 13:55
+     * @Param [str]
+     * @return boolean
+     **/
+    public static boolean isEmpty(String str) {
+        return str == null || "".equals(str.trim()) || "null".equals(str.trim());
+    }
+
+    public static boolean isBlank(Map param, String str) {
+        return !param.containsKey(str) || param.get(str) == null || "".equals(param.get(str).toString().trim()) || "null".equals(param.get(str).toString().trim());
+    }
+
+    public static boolean isNotBlank(Map param, String str) {
+        return !isBlank(param, str);
+    }
+
+    /***
+     * @Author JI
+     * @Description //������������������������������������������
+     * @Date 2020/3/27 13:55
+     * @Param [str]
+     * @return boolean
+     **/
+    public static boolean isNotEmpty(String str) {
+        return !isEmpty(str);
+    }
+
+    /**
+     * <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>
+     *
+     * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
+     *
+     * <pre>
+     * StringUtils.isBlank(null)      = true
+     * StringUtils.isBlank("")        = true
+     * StringUtils.isBlank(" ")       = true
+     * StringUtils.isBlank("bob")     = false
+     * StringUtils.isBlank("  bob  ") = false
+     * </pre>
+     *
+     * @param cs the CharSequence to check, may be null
+     * @return {@code true} if the CharSequence is null, empty or whitespace only
+     * @since 2.0
+     * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
+     */
+    public static boolean isBlank(final CharSequence cs) {
+        int strLen;
+        if (cs == null || (strLen = cs.length()) == 0) {
+            return true;
+        }
+        for (int i = 0; i < strLen; i++) {
+            if (!Character.isWhitespace(cs.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * ������������������<code>null</code>������������������������������������������������������������������
+     * <p>
+     * <pre>
+     * nullToDefault(null, &quot;default&quot;)  = &quot;default&quot;
+     * nullToDefault(&quot;&quot;, &quot;default&quot;)    = &quot;&quot;
+     * nullToDefault(&quot;  &quot;, &quot;default&quot;)  = &quot;  &quot;
+     * nullToDefault(&quot;bat&quot;, &quot;default&quot;) = &quot;bat&quot;
+     * </pre>
+     *
+     * @param str        ���������������������
+     * @param defaultStr ���������������
+     * @return ������������������������������������������
+     */
+    public static String nullToDefault(String str, String defaultStr) {
+        return (str == null) ? defaultStr : str;
+    }
+
+    /**
+     * ������������������������������������������������<code>null</code>
+     *
+     * @param str ���������������������
+     * @return ���������������������
+     */
+    public static String emptyToNull(String str) {
+        return isEmpty(str) ? null : str;
+    }
+
+    /**
+     * ������������������������
+     *
+     * @param strs ���������������
+     * @return ������������������������
+     */
+    public static boolean hasEmpty(String... strs) {
+        for (String str : strs) {
+            if (isEmpty(str)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * ���������������������������
+     *
+     * @param strs ���������������
+     * @return ���������������������������
+     */
+    public static boolean isAllEmpty(String... strs) {
+
+        for (String str : strs) {
+            if (isNotEmpty(str)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * ������������������������������
+     *
+     * @param str          ������������������
+     * @param prefix       ���������������
+     * @param isIgnoreCase ���������������������
+     * @return ������������������������������
+     */
+    public static boolean startWith(String str, String prefix, boolean isIgnoreCase) {
+        if (isIgnoreCase) {
+            return str.toLowerCase().startsWith(prefix.toLowerCase());
+        } else {
+            return str.startsWith(prefix);
+        }
+    }
+
+    /**
+     * ������������������������������
+     *
+     * @param str          ������������������
+     * @param suffix       ���������������
+     * @param isIgnoreCase ���������������������
+     * @return ������������������������������
+     */
+    public static boolean endWith(String str, String suffix, boolean isIgnoreCase) {
+        if (isIgnoreCase) {
+            return str.toLowerCase().endsWith(suffix.toLowerCase());
+        } else {
+            return str.endsWith(suffix);
+        }
+    }
+
+    /**
+     * ���������������������������������������������������������������������������<code>null</code>���������true
+     *
+     * @param str     ������������������
+     * @param testStr ���������������������������������
+     * @return ������������
+     */
+    public static boolean containsIgnoreCase(String str, String testStr) {
+        if (null == str) {
+            //���������������������������
+            return null == testStr;
+        }
+        return str.toLowerCase().contains(testStr.toLowerCase());
+    }
+
+    /**
+     * ������set���������<br/>
+     * ���������name ������ setName
+     *
+     * @param fieldName ���������
+     * @return setXxx
+     */
+    public static String genSetter(String fieldName) {
+        return upperFirstAndAddPre(fieldName, "set");
+    }
+
+    /**
+     * ������get���������
+     *
+     * @param fieldName ���������
+     * @return getXxx
+     */
+    public static String genGetter(String fieldName) {
+        return upperFirstAndAddPre(fieldName, "get");
+    }
+
+    /**
+     * ������������������������������������������������������������������������<br/>
+     * ���������str=setName, preLength=3 -> return name
+     *
+     * @param str       ���������������������
+     * @param preLength ���������������
+     * @return ���������������������������������������������null
+     */
+    public static String cutPreAndLowerFirst(String str, int preLength) {
+        if (str == null) {
+            return null;
+        }
+        if (str.length() > preLength) {
+            char first = Character.toLowerCase(str.charAt(preLength));
+            if (str.length() > preLength + 1) {
+                return first + str.substring(preLength + 1);
+            }
+            return String.valueOf(first);
+        }
+        return null;
+    }
+
+    /**
+     * ��������������������������������������������������������������� ���������str=name, preString=get -> return getName
+     *
+     * @param str       ���������������������
+     * @param preString ���������������
+     * @return ���������������������
+     */
+    public static String upperFirstAndAddPre(String str, String preString) {
+        if (str == null || preString == null) {
+            return null;
+        }
+        return preString + capitalize(str);
+    }
+
+
+    /**
+     * ������������������
+     *
+     * @param str    ���������
+     * @param prefix ������
+     * @return ��������������������������������������� preffix��� ������������������
+     */
+    public static String removePrefix(String str, String prefix) {
+        if (isEmpty(str) || isEmpty(prefix)) {
+            return str;
+        }
+
+        if (str.startsWith(prefix)) {
+            return str.substring(prefix.length());
+        }
+        return str;
+    }
+
+    /**
+     * ���������������������������������
+     *
+     * @param str    ���������
+     * @param prefix ������
+     * @return ��������������������������������������� prefix��� ������������������
+     */
+    public static String removePrefixIgnoreCase(String str, String prefix) {
+        if (isEmpty(str) || isEmpty(prefix)) {
+            return str;
+        }
+
+        if (str.toLowerCase().startsWith(prefix.toLowerCase())) {
+            return str.substring(prefix.length());
+        }
+        return str;
+    }
+
+    /**
+     * ������������������
+     *
+     * @param str    ���������
+     * @param suffix ������
+     * @return ��������������������������������������� suffix��� ������������������
+     */
+    public static String removeSuffix(String str, String suffix) {
+        if (isEmpty(str) || isEmpty(suffix)) {
+            return str;
+        }
+
+        if (str.endsWith(suffix)) {
+            return str.substring(0, str.length() - suffix.length());
+        }
+        return str;
+    }
+
+    /**
+     * ���������������������byte������
+     *
+     * @param str     ���������
+     * @param charset ������������������<code>null</code>������������������������
+     * @return bytes
+     */
+    public static byte[] getBytes(String str, Charset charset) {
+        if (null == str) {
+            return null;
+        }
+        return null == charset ? str.getBytes() : str.getBytes(charset);
+    }
+
+    /**
+     * ���������������������������������
+     *
+     * @param str    ���������
+     * @param suffix ������
+     * @return ��������������������������������������� suffix��� ������������������
+     */
+    public static String removeSuffixIgnoreCase(String str, String suffix) {
+        if (isEmpty(str) || isEmpty(suffix)) {
+            return str;
+        }
+
+        if (str.toLowerCase().endsWith(suffix.toLowerCase())) {
+            return str.substring(0, str.length() - suffix.length());
+        }
+        return str;
+    }
+
+    /**
+     * ������������������������������prefix��������������������������� prefix
+     *
+     * @param str    ���������
+     * @param prefix ������
+     * @return ���������������������
+     */
+    public static String addPrefixIfNot(String str, String prefix) {
+        if (isEmpty(str) || isEmpty(prefix)) {
+            return str;
+        }
+        if (!str.startsWith(prefix)) {
+            str = prefix + str;
+        }
+        return str;
+    }
+
+    /**
+     * ������������������������������suffix��������������������������� suffix
+     *
+     * @param str    ���������
+     * @param suffix ������
+     * @return ���������������������
+     */
+    public static String addSuffixIfNot(String str, String suffix) {
+        if (isEmpty(str) || isEmpty(suffix)) {
+            return str;
+        }
+        if (!str.endsWith(suffix)) {
+            str += suffix;
+        }
+        return str;
+    }
+
+    /**
+     * ������������������
+     *
+     * @param str ���������������������
+     * @return ���������������������
+     */
+    public static String cleanBlank(String str) {
+        if (str == null) {
+            return null;
+        }
+
+        return str.replaceAll("\\s*", EMPTY);
+    }
+
+    /**
+     * ���������������<br>
+     * from jodd
+     *
+     * @param str       ���������������������
+     * @param delimiter ���������
+     * @return ���������
+     */
+    public static String[] split(String str, String delimiter) {
+        if (str == null) {
+            return null;
+        }
+        if (str.trim().length() == 0) {
+            return new String[]{str};
+        }
+        // del length
+        int dellen = delimiter.length();
+        // one more for the last
+        int maxparts = (str.length() / dellen) + 2;
+        int[] positions = new int[maxparts];
+
+        int i, j = 0;
+        int count = 0;
+        positions[0] = -dellen;
+        while ((i = str.indexOf(delimiter, j)) != -1) {
+            count++;
+            positions[count] = i;
+            j = i + dellen;
+        }
+        count++;
+        positions[count] = str.length();
+
+        String[] result = new String[count];
+
+        for (i = 0; i < count; i++) {
+            result[i] = str.substring(positions[i] + dellen, positions[i + 1]);
+        }
+        return result;
+    }
+
+    /**
+     * ������JDK subString<br>
+     * index���0������������������������������������-1<br>
+     * ������from���to��������������������� "" <br>
+     * ������from���to���������������������length������������������������������������������������������������������from������0���to������length<br>
+     * ���������������������index���from������to������������from���to
+     * example: <br>
+     * abcdefgh 2 3 -> c <br>
+     * abcdefgh 2 -3 -> cde <br>
+     *
+     * @param string    String
+     * @param fromIndex ���������index������������
+     * @param toIndex   ���������index���������������
+     * @return ������
+     */
+    public static String sub(String string, int fromIndex, int toIndex) {
+        int len = string.length();
+        if (fromIndex < 0) {
+            fromIndex = len + fromIndex;
+            if (fromIndex < 0) {
+                fromIndex = 0;
+            }
+        } else if (fromIndex >= len) {
+            fromIndex = len - 1;
+        }
+        if (toIndex < 0) {
+            toIndex = len + toIndex;
+            if (toIndex < 0) {
+                toIndex = len;
+            }
+        } else if (toIndex > len) {
+            toIndex = len;
+        }
+        if (toIndex < fromIndex) {
+            int tmp = fromIndex;
+            fromIndex = toIndex;
+            toIndex = tmp;
+        }
+        if (fromIndex == toIndex) {
+            return EMPTY;
+        }
+        char[] strArray = string.toCharArray();
+        char[] newStrArray = Arrays.copyOfRange(strArray, fromIndex, toIndex);
+        return new String(newStrArray);
+    }
+
+    /**
+     * ���������������
+     *
+     * @param string  ���������
+     * @param toIndex ���������������������������������
+     * @return ���������������������
+     */
+    public static String subPre(String string, int toIndex) {
+        return sub(string, 0, toIndex);
+    }
+
+    /**
+     * ���������������
+     *
+     * @param string    ���������
+     * @param fromIndex ���������������������������������
+     * @return ���������������������
+     */
+    public static String subSuf(String string, int fromIndex) {
+        if (isEmpty(string)) {
+            return null;
+        }
+        return sub(string, fromIndex, string.length());
+    }
+
+    /**
+     * ������������������������������������
+     *
+     * @param str    ���������
+     * @param prefix ������
+     * @param suffix ������
+     * @return ������������������������������
+     */
+    public static boolean isSurround(String str, String prefix, String suffix) {
+        if (StringUtils.isBlank(str)) {
+            return false;
+        }
+        if (str.length() < (prefix.length() + suffix.length())) {
+            return false;
+        }
+
+        return str.startsWith(prefix) && str.endsWith(suffix);
+    }
+
+//    /**
+//     * ������������������������������������
+//     *
+//     * @param str    ���������
+//     * @param prefix ������
+//     * @param suffix ������
+//     * @return ������������������������������
+//     */
+//    public static boolean isSurround(String str, char prefix, char suffix) {
+//        if (StringUtils.isBlank(str)) {
+//            return false;
+//        }
+//        if (str.length() < 2) {
+//            return false;
+//        }
+//
+//        return str.charAt(0) == prefix && str.charAt(str.length() - 1) == suffix;
+//    }
+
+    /**
+     * ������������������
+     *
+     * @param c     ������������������
+     * @param count ���������������
+     * @return ���������������������
+     */
+    public static String repeat(char c, int count) {
+        char[] result = new char[count];
+        for (int i = 0; i < count; i++) {
+            result[i] = c;
+        }
+        return new String(result);
+    }
+
+    /**
+     * ���������������������
+     *
+     * @param str   ������������������
+     * @param count ���������������
+     * @return ���������������������
+     */
+    public static String repeat(String str, int count) {
+
+        // ������
+        final int len = str.length();
+        final long longSize = (long) len * (long) count;
+        final int size = (int) longSize;
+        if (size != longSize) {
+            throw new ArrayIndexOutOfBoundsException("Required String length is too large: " + longSize);
+        }
+
+        final char[] array = new char[size];
+        str.getChars(0, len, array, 0);
+        int n;
+        // n <<= 1���������n *2
+        for (n = len; n < size - n; n <<= 1) {
+            System.arraycopy(array, 0, array, n, n);
+        }
+        System.arraycopy(array, 0, array, n, size - n);
+        return new String(array);
+    }
+
+    /**
+     * ���������������������������������������������
+     * <p>
+     * <pre>
+     * equals(null, null)   = true
+     * equals(null, &quot;abc&quot;)  = false
+     * equals(&quot;abc&quot;, null)  = false
+     * equals(&quot;abc&quot;, &quot;abc&quot;) = true
+     * equals(&quot;abc&quot;, &quot;ABC&quot;) = false
+     * </pre>
+     *
+     * @param str1 ���������������������1
+     * @param str2 ���������������������2
+     * @return ������������������������������������������<code>null</code>������������<code>true</code>
+     */
+    public static boolean equals(String str1, String str2) {
+        if (str1 == null) {
+            return str2 == null;
+        }
+
+        return str1.equals(str2);
+    }
+
+    /**
+     * ������������������������������������������������
+     * <p>
+     * <pre>
+     * equalsIgnoreCase(null, null)   = true
+     * equalsIgnoreCase(null, &quot;abc&quot;)  = false
+     * equalsIgnoreCase(&quot;abc&quot;, null)  = false
+     * equalsIgnoreCase(&quot;abc&quot;, &quot;abc&quot;) = true
+     * equalsIgnoreCase(&quot;abc&quot;, &quot;ABC&quot;) = true
+     * </pre>
+     *
+     * @param str1 ���������������������1
+     * @param str2 ���������������������2
+     * @return ������������������������������������������<code>null</code>������������<code>true</code>
+     */
+    public static boolean equalsIgnoreCase(String str1, String str2) {
+        if (str1 == null) {
+            return str2 == null;
+        }
+
+        return str1.equalsIgnoreCase(str2);
+    }
+
+    /**
+     * ���������������, {} ���������������<br>
+     * ���������format("aaa {} ccc", "bbb")   ---->    aaa bbb ccc
+     *
+     * @param template ������������������������������������ {} ������
+     * @param values   ���������
+     * @return ���������������������
+     */
+    public static String format(String template, Object... values) {
+        if (isBlank(template)) {
+            return template;
+        }
+
+        final StringBuilder sb = new StringBuilder();
+        final int length = template.length();
+
+        int valueIndex = 0;
+        char currentChar;
+        for (int i = 0; i < length; i++) {
+            if (valueIndex >= values.length) {
+                sb.append(sub(template, i, length));
+                break;
+            }
+
+            currentChar = template.charAt(i);
+            if (currentChar == '{') {
+                final char nextChar = template.charAt(++i);
+                if (nextChar == '}') {
+                    sb.append(values[valueIndex++]);
+                } else {
+                    sb.append('{').append(nextChar);
+                }
+            } else {
+                sb.append(currentChar);
+            }
+
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * ������������������������ {varName} ������<br>
+     * map = {a: "aValue", b: "bValue"}
+     * format("{a} and {b}", map)    ---->    aValue and bValue
+     *
+     * @param template ������������������������������������ {key} ������
+     * @param map      ������������
+     * @return ���������������������
+     */
+    public static String format(String template, Map<?, ?> map) {
+        if (null == map || map.isEmpty()) {
+            return template;
+        }
+
+        for (Map.Entry<?, ?> entry : map.entrySet()) {
+            template = template.replace("{" + entry.getKey() + "}", entry.getValue().toString());
+        }
+        return template;
+    }
+
+    /**
+     * ���������������
+     *
+     * @param str     ���������
+     * @param charset ���������������������������������������������������������������������
+     * @return ���������������������
+     */
+    public static byte[] bytes(String str, String charset) {
+        return bytes(str, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+    }
+
+    /**
+     * ���������������
+     *
+     * @param str     ���������
+     * @param charset ���������������������������������������������������������������������
+     * @return ���������������������
+     */
+    public static byte[] bytes(String str, Charset charset) {
+        if (str == null) {
+            return null;
+        }
+
+        if (null == charset) {
+            return str.getBytes();
+        }
+        return str.getBytes(charset);
+    }
+
+    /**
+     * ���byte���������������������
+     *
+     * @param bytes   byte������
+     * @param charset ���������
+     * @return ���������
+     */
+    public static String str(byte[] bytes, String charset) {
+        return str(bytes, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+    }
+
+    /**
+     * ���������������
+     *
+     * @param data    ���������
+     * @param charset ���������������������������������������������������������������������
+     * @return ���������������������
+     */
+    public static String str(byte[] data, Charset charset) {
+        if (data == null) {
+            return null;
+        }
+
+        if (null == charset) {
+            return new String(data);
+        }
+        return new String(data, charset);
+    }
+
+    /**
+     * ������������byteBuffer������������������������
+     *
+     * @param data    ������
+     * @param charset ���������������������������������������������������
+     * @return ���������
+     */
+    public static String str(ByteBuffer data, String charset) {
+        if (data == null) {
+            return null;
+        }
+
+        return str(data, Charset.forName(charset));
+    }
+
+    /**
+     * ������������byteBuffer������������������������
+     *
+     * @param data    ������
+     * @param charset ���������������������������������������������������
+     * @return ���������
+     */
+    public static String str(ByteBuffer data, Charset charset) {
+        if (null == charset) {
+            charset = Charset.defaultCharset();
+        }
+        return charset.decode(data).toString();
+    }
+
+    /**
+     * ������������������byteBuffer
+     *
+     * @param str     ���������
+     * @param charset ������
+     * @return byteBuffer
+     */
+    public static ByteBuffer byteBuffer(String str, String charset) {
+        return ByteBuffer.wrap(StringUtils.bytes(str, charset));
+    }
+
+    /**
+     * ��� conjunction ���������������������������������������������
+     *
+     * @param conjunction ���������
+     * @param objs        ������
+     * @return ���������������������
+     */
+    public static String join(String conjunction, Object... objs) {
+        StringBuilder sb = new StringBuilder();
+        boolean isFirst = true;
+        for (Object item : objs) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(conjunction);
+            }
+            sb.append(item);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * ���������������������������������������������������������������������������������������������������������������������������������������</br>
+     * ���������HelloWorld->hello_world
+     *
+     * @param camelCaseStr ���������������������������������������
+     * @return ������������������������������������������������
+     */
+    public static String camelCaseToPath(String camelCaseStr) {
+        if (camelCaseStr == null) {
+            return null;
+        }
+
+        final int length = camelCaseStr.length();
+        StringBuilder sb = new StringBuilder();
+        char c;
+        boolean isPreUpperCase = false;
+        for (int i = 0; i < length; i++) {
+            c = camelCaseStr.charAt(i);
+            boolean isNextUpperCase = true;
+            if (i < (length - 1)) {
+                isNextUpperCase = Character.isUpperCase(camelCaseStr.charAt(i + 1));
+            }
+            if (Character.isUpperCase(c)) {
+                if (!isPreUpperCase || !isNextUpperCase) {
+                    if (i > 0) {
+                        sb.append("/");
+                    }
+                }
+                isPreUpperCase = true;
+            } else {
+                isPreUpperCase = false;
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * ���������������������������������������������������������������������������������������������������������������������������������������</br>
+     * ���������HelloWorld->hello_world
+     *
+     * @param camelCaseStr ���������������������������������������
+     * @return ������������������������������������������������
+     */
+    public static String camelCaseToUnderline(String camelCaseStr) {
+        if (camelCaseStr == null) {
+            return null;
+        }
+
+        final int length = camelCaseStr.length();
+        StringBuilder sb = new StringBuilder();
+        char c;
+        boolean isPreUpperCase = false;
+        for (int i = 0; i < length; i++) {
+            c = camelCaseStr.charAt(i);
+            boolean isNextUpperCase = true;
+            if (i < (length - 1)) {
+                isNextUpperCase = Character.isUpperCase(camelCaseStr.charAt(i + 1));
+            }
+            if (Character.isUpperCase(c)) {
+                if (!isPreUpperCase || !isNextUpperCase) {
+                    if (i > 0) {
+                        sb.append(UNDERLINE);
+                    }
+                }
+                isPreUpperCase = true;
+            } else {
+                isPreUpperCase = false;
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * ���������������������������������������������������������������������������������������������������������������������������������������������������</br>
+     * ���������hello_world->HelloWorld
+     *
+     * @param name ���������������������������������������������������
+     * @return ���������������������������������������
+     */
+    public static String underlineToCamelCase(String name) {
+        if (name == null) {
+            return null;
+        }
+        if (name.contains(UNDERLINE)) {
+            name = name.toLowerCase();
+
+            StringBuilder sb = new StringBuilder(name.length());
+            boolean upperCase = false;
+            for (int i = 0; i < name.length(); i++) {
+                char c = name.charAt(i);
+
+                if (c == '_') {
+                    upperCase = true;
+                } else if (upperCase) {
+                    sb.append(Character.toUpperCase(c));
+                    upperCase = false;
+                } else {
+                    sb.append(c);
+                }
+            }
+            return sb.toString();
+        } else {
+            return name;
+        }
+    }
+
+    /**
+     * ���������������������
+     *
+     * @param str    ���������������������
+     * @param prefix ������
+     * @param suffix ������
+     * @return ���������������������
+     */
+    public static String wrap(String str, String prefix, String suffix) {
+        return format("{}{}{}", prefix, str, suffix);
+    }
+
+    /**
+     * ������������������������������
+     *
+     * @param str    ���������
+     * @param prefix ������
+     * @param suffix ������
+     * @return ���������������
+     */
+    public static boolean isWrap(String str, String prefix, String suffix) {
+        return str.startsWith(prefix) && str.endsWith(suffix);
+    }
+
+    /**
+     * ���������������������������������������������������������������������������
+     *
+     * @param str     ���������
+     * @param wrapper ���������������
+     * @return ���������������
+     */
+    public static boolean isWrap(String str, String wrapper) {
+        return isWrap(str, wrapper, wrapper);
+    }
+
+    /**
+     * ���������������������������������������������������������������������������
+     *
+     * @param str     ���������
+     * @param wrapper ������������
+     * @return ���������������
+     */
+    public static boolean isWrap(String str, char wrapper) {
+        return isWrap(str, wrapper, wrapper);
+    }
+
+    /**
+     * ������������������������������
+     *
+     * @param str        ���������
+     * @param prefixChar ������
+     * @param suffixChar ������
+     * @return ���������������
+     */
+    public static boolean isWrap(String str, char prefixChar, char suffixChar) {
+        return str.charAt(0) == prefixChar && str.charAt(str.length() - 1) == suffixChar;
+    }
+
+    /**
+     * ������StringBuilder������
+     *
+     * @return StringBuilder������
+     */
+    public static StringBuilder builder() {
+        return new StringBuilder();
+    }
+
+    /**
+     * ������StringBuilder������
+     *
+     * @return StringBuilder������
+     */
+    public static StringBuilder builder(int capacity) {
+        return new StringBuilder(capacity);
+    }
+
+    /**
+     * ������StringBuilder������
+     *
+     * @return StringBuilder������
+     */
+    public static StringBuilder builder(String... strs) {
+        final StringBuilder sb = new StringBuilder();
+        for (String str : strs) {
+            sb.append(str);
+        }
+        return sb;
+    }
+
+
+    public static String concatLikeStart(String value) {
+        return concatLike(value, 1);
+    }
+
+    public static String concatLikeEnd(String value) {
+        return concatLike(value, 2);
+    }
+
+    public static String concatLikeAll(String value) {
+        return concatLike(value, -1);
+    }
+
+    /**
+     * @param value
+     * @param type
+     * @return
+     */
+    public static String concatLike(String value, Integer type) {
+        if (isEmpty(value)) {
+            return null;
+        }
+        StringBuilder builder = new StringBuilder(value.length() + 3);
+        switch (type) {
+            case 1:
+                builder.append("%").append(value);
+                break;
+            case 2:
+                builder.append(value).append("%");
+                break;
+            case 3:
+                builder.append(value);
+                break;
+            default:
+                builder.append("%").append(value).append("%");
+        }
+        return builder.toString();
+    }
+
+    /**
+     * ������StringReader
+     *
+     * @param str ���������
+     * @return StringReader
+     */
+    public static StringReader getReader(String str) {
+        return new StringReader(str);
+    }
+
+    /**
+     * ������StringWriter
+     *
+     * @return StringWriter
+     */
+    public static StringWriter getWriter() {
+        return new StringWriter();
+    }
+
+    /**
+     * ���������������
+     *
+     * @param str     ���������
+     * @param charset ���������������������������������������������������������������������
+     * @return ���������������������
+     */
+    public static byte[] encode(String str, String charset) {
+        if (str == null) {
+            return null;
+        }
+
+        if (isBlank(charset)) {
+            return str.getBytes();
+        }
+        try {
+            return str.getBytes(charset);
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(format("Charset [{}] unsupported!", charset));
+        }
+    }
+
+    /**
+     * ���������������
+     *
+     * @param data    ���������
+     * @param charset ���������������������������������������������������������������������
+     * @return ���������������������
+     */
+    public static String decode(byte[] data, String charset) {
+        if (data == null) {
+            return null;
+        }
+
+        if (isBlank(charset)) {
+            return new String(data);
+        }
+        try {
+            return new String(data, charset);
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(format("Charset [{}] unsupported!", charset));
+        }
+    }
+
+//    /**
+//     * ������������������
+//     */
+//    public static String firstCharToUpperCase(String str) {
+//        char firstChar = str.charAt(0);
+//        if (firstChar >= 'a' && firstChar <= 'z') {
+//            char[] arr = str.toCharArray();
+//            arr[0] -= ('a' - 'A');
+//            return new String(arr);
+//        }
+//        return str;
+//    }
+
+
+    /**
+     * Description:������������������������������������������������������������������������0������������������������������������������������
+     * ���������23���������4��������������� => "0023"
+     *
+     * @param val ���������
+     * @param num ���������������
+     * @return java.lang.String
+     * @author fanhq
+     * @date 2020/4/17 9:44
+     */
+    public static String intToStringCode(Integer val, Integer num) {
+        int i = num - val.toString().length();
+        StringBuffer sbf = new StringBuffer();
+        for (int k = 0; k < i; k++) {
+            sbf.append("0");
+        }
+        return sbf.append(val.toString()).toString();
+    }
+
+    public static String match(String message, String regex) {
+        Pattern p = Pattern.compile(regex);
+        Matcher m = p.matcher(message);
+        while (m.find()) {
+            return m.group();
+        }
+        return null;
+    }
+
+    public static String lpad(Integer length, String data, char text) {
+        if (data.length() >= length) {
+            return data;
+        }
+        StringBuffer stringBuffer = new StringBuffer();
+        for (int i = data.length(); i < length; i++) {
+            stringBuffer.append(text);
+        }
+        return stringBuffer.append(data).toString();
+    }
+}
diff --git a/screen-api/src/main/resources/application-dev.yml b/screen-api/src/main/resources/application-dev.yml
index 0dc6f52..71d7a11 100644
--- a/screen-api/src/main/resources/application-dev.yml
+++ b/screen-api/src/main/resources/application-dev.yml
@@ -115,10 +115,12 @@
       - /webjars/**
       - /verificationCode/**
       - /static/**
-
+      - /file/preview/**
 AES:
   KEY:
     AD42F7787B035B7580000EF93BE20BAD
 TOKEN:
   KEY:
-    foh3wi2ooghiCh5
\ No newline at end of file
+    foh3wi2ooghiCh5
+file:
+  path: /data/upload/
\ No newline at end of file
diff --git a/screen-api/src/main/resources/application-qa.yml b/screen-api/src/main/resources/application-qa.yml
index ab0f0ae..589ed97 100644
--- a/screen-api/src/main/resources/application-qa.yml
+++ b/screen-api/src/main/resources/application-qa.yml
@@ -128,7 +128,7 @@
       - /webjars/**
       - /verificationCode/**
       - /static/**
-      - /file/**
+      - /file/preview/**
 
 
 AES:
@@ -138,3 +138,5 @@
   KEY:
     foh3wi2ooghiCh5
 
+file:
+  path: E:\upload
\ No newline at end of file
diff --git a/screen-api/src/main/resources/mapper/FileTableMapper.xml b/screen-api/src/main/resources/mapper/FileTableMapper.xml
new file mode 100644
index 0000000..3f57c01
--- /dev/null
+++ b/screen-api/src/main/resources/mapper/FileTableMapper.xml
@@ -0,0 +1,20 @@
+<?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.moral.api.mapper.FileTableMapper">
+
+        <!-- ������������������������ -->
+        <resultMap id="BaseResultMap" type="com.moral.api.entity.FileTable">
+                    <id column="file_id" property="fileId" />
+                    <result column="file_module" property="fileModule" />
+                    <result column="relation_id" property="relationId" />
+                    <result column="file_name" property="fileName" />
+                    <result column="file_type" property="fileType" />
+                    <result column="file_address" property="fileAddress" />
+                    <result column="file_size" property="fileSize" />
+                    <result column="is_del" property="isDel" />
+                    <result column="create_id" property="createId" />
+                    <result column="create_name" property="createName" />
+                    <result column="create_time" property="createTime" />
+        </resultMap>
+
+</mapper>
\ No newline at end of file

--
Gitblit v1.8.0