Bladeren bron

文件服务完善,只提供本地上传服务,且对返回路径进行加密,加密后解决url传递参数有特殊字符问题

gaoxiong 2 jaren geleden
bovenliggende
commit
e4cabb4c70

+ 5 - 0
soc-modules/soc-modules-file/pom.xml

@@ -56,6 +56,11 @@
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
 
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 29 - 1
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/controller/SysFileController.java

@@ -3,14 +3,19 @@ package com.xunmei.file.controller;
 import com.xunmei.common.core.domain.R;
 import com.xunmei.common.core.utils.file.FileUtils;
 import com.xunmei.file.service.ISysFileService;
+import com.xunmei.file.utils.DesUtil;
 import com.xunmei.system.api.domain.SysFile;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
+
 /**
  * 文件请求处理
  * 
@@ -25,6 +30,15 @@ public class SysFileController
     private ISysFileService sysFileService;
 
     /**
+     * 路径加密秘钥
+     */
+    @Value("${file.secretKey}")
+    public String secretKey;
+
+
+    private static final String FILE_SUFFIX = "FILE_CODE_";
+
+    /**
      * 文件上传请求
      */
     @PostMapping("upload")
@@ -36,7 +50,9 @@ public class SysFileController
             String url = sysFileService.uploadFile(file);
             SysFile sysFile = new SysFile();
             sysFile.setName(FileUtils.getName(url));
-            sysFile.setUrl(url);
+            sysFile.setUrl(null);
+            String code = DesUtil.encrypt(url, secretKey);
+            sysFile.setCode(code);
             return R.ok(sysFile);
         }
         catch (Exception e)
@@ -45,4 +61,16 @@ public class SysFileController
             return R.fail(e.getMessage());
         }
     }
+
+    @PostMapping("/downloadFile")
+    public void downloadFile(HttpServletResponse response,@RequestBody SysFile sysFile){
+        try {
+            String filePath = DesUtil.decode(sysFile.getCode(), secretKey);
+            sysFileService.downloadFile(response,filePath);
+        } catch (Exception e) {
+            log.error("下载文件失败", e);
+            throw new RuntimeException(e);
+        }
+
+    }
 }

+ 13 - 1
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/service/ISysFileService.java

@@ -2,6 +2,9 @@ package com.xunmei.file.service;
 
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+
 /**
  * 文件上传接口
  * 
@@ -16,5 +19,14 @@ public interface ISysFileService
      * @return 访问地址
      * @throws Exception
      */
-    public String uploadFile(MultipartFile file) throws Exception;
+     String uploadFile(MultipartFile file) throws Exception;
+
+    /**
+     * 文件下载接口
+     * @param response
+     * @param filePath
+     * @return
+     * @throws Exception
+     */
+    void downloadFile(HttpServletResponse response,String filePath)throws Exception;
 }

+ 58 - 13
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/service/LocalSysFileServiceImpl.java

@@ -1,11 +1,24 @@
 package com.xunmei.file.service;
 
+import com.xunmei.common.core.utils.uuid.UUID;
+import com.xunmei.file.utils.FileDownUtils;
 import com.xunmei.file.utils.FileUploadUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Primary;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+
 /**
  * 本地文件存储
  * 
@@ -15,24 +28,18 @@ import org.springframework.web.multipart.MultipartFile;
 @Service
 public class LocalSysFileServiceImpl implements ISysFileService
 {
-    /**
-     * 资源映射路径 前缀
-     */
-    @Value("${file.prefix}")
-    public String localFilePrefix;
 
-    /**
-     * 域名或本机访问地址
-     */
-    @Value("${file.domain}")
-    public String domain;
-    
+    private static final Logger log = LoggerFactory.getLogger(LocalSysFileServiceImpl.class);
+
     /**
      * 上传文件存储在本地的根路径
      */
     @Value("${file.path}")
     private String localFilePath;
 
+    @Autowired
+    private HttpServletRequest request;
+
     /**
      * 本地文件上传接口
      * 
@@ -44,7 +51,45 @@ public class LocalSysFileServiceImpl implements ISysFileService
     public String uploadFile(MultipartFile file) throws Exception
     {
         String name = FileUploadUtils.upload(localFilePath, file);
-        String url = domain + localFilePrefix + name;
-        return url;
+//        String url = domain + localFilePrefix + name;
+        return name;
+    }
+
+    @Override
+    public void downloadFile(HttpServletResponse response, String filePath){
+        ByteArrayOutputStream out = null;
+        try {
+            filePath = localFilePath + filePath;
+            filePath = URLDecoder.decode(filePath,"UTF-8");
+            out = FileDownUtils.downloadFile(filePath);
+            String fileSuffix = FileDownUtils.getFileSuffix(filePath);
+            String formFileName = UUID.randomUUID().toString() + fileSuffix;
+            String userAgent = request.getHeader("User-Agent");
+
+            // 针对IE或者以IE为内核的浏览器:
+            if (StringUtils.isNotEmpty(userAgent) && (userAgent.contains("MSIE") || userAgent.contains("Trident"))) {
+                formFileName = java.net.URLEncoder.encode(formFileName, "UTF-8");
+            } else {
+                // 非IE浏览器的处理:
+                formFileName = new String(formFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
+            }
+            response.reset();
+            response.setCharacterEncoding("UTF-8");
+            response.addHeader("Content-Disposition", "attachment;filename=" + formFileName);
+            response.addHeader("Content-Length", "" + out.size());
+            out.writeTo(response.getOutputStream());
+            response.setContentType("application/octet-stream");
+            out.flush();
+            out.close();
+        } catch (IOException e) {
+            log.error("文件下载失败! ");
+            e.printStackTrace();
+        } finally {
+            try {
+                out.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
     }
 }

+ 60 - 0
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/utils/DesUtil.java

@@ -0,0 +1,60 @@
+package com.xunmei.file.utils;
+import cn.hutool.crypto.SecureUtil;
+import cn.hutool.crypto.symmetric.DES;
+import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
+import sun.misc.BASE64Decoder;
+import sun.misc.BASE64Encoder;
+
+import java.io.IOException;
+
+/**
+ * @Description: Des 加解密工具
+ */
+public class DesUtil {
+
+    /**
+     * 加密
+     *
+     * @param info
+     * @return
+     */
+    public static String encrypt(String info, String secretKey) {
+        byte[] key = new byte[0];
+        try {
+            key = new BASE64Decoder().decodeBuffer(secretKey);
+        } catch (IOException ioException) {
+            ioException.printStackTrace();
+        }
+        DES des = SecureUtil.des(key);
+        String encrypt = des.encryptHex(info);
+        return encrypt;
+    }
+
+    /**
+     * 解密
+     *
+     * @param encrypt
+     * @return
+     */
+    public static String decode(String encrypt, String secretKey) throws IOException {
+        byte[] key = new byte[0];
+        key = new BASE64Decoder().decodeBuffer(secretKey);
+        DES des = SecureUtil.des(key);
+        return des.decryptStr(encrypt);
+    }
+
+
+
+    public static void main(String[] args) throws IOException {
+        //生成密钥,并转为字符串,可以储存起来,解密时可直接使用
+        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue()).getEncoded();
+        String secretKey = new BASE64Encoder().encodeBuffer(key);
+        System.out.println(secretKey);
+        String admin = DesUtil.encrypt("/ddatat/tata/tat", secretKey);
+        System.out.println(admin);
+
+        // 解密
+        String adminDecode = DesUtil.decode(admin, secretKey);
+        System.out.println(adminDecode);
+    }
+}

+ 89 - 0
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/utils/FileDownUtils.java

@@ -0,0 +1,89 @@
+package com.xunmei.file.utils;
+
+import com.xunmei.file.controller.SysFileController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+
+/**
+ * 文件下载工具
+ * @author gaoxiong
+ */
+public class FileDownUtils {
+
+    private static final Logger log = LoggerFactory.getLogger(FileDownUtils.class);
+
+
+
+    /**
+     * 下载文件
+     * @param filePath 文件地址
+     * @return
+     */
+    public static ByteArrayOutputStream downloadFile(String filePath) {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new RuntimeException("文件不存在!");
+        }
+        InputStream is = getInputStream(file);
+        return convertInputStream(is);
+    }
+
+    /**
+     * 获取文件输入流
+     * @param file 文件对象
+     * @return 文件输入流对象
+     */
+    public static InputStream getInputStream(File file) {
+        FileInputStream fin;
+        try {
+            fin = new FileInputStream(file);
+        } catch (FileNotFoundException e) {
+            if (log.isDebugEnabled()) {
+                log.debug(String.valueOf(e));
+            }
+            String msg = "找不到指定的文件[" + file.getName() + "]。";
+            if (log.isDebugEnabled()) {
+                log.debug(msg);
+            }
+            throw new RuntimeException(msg, e);
+        }
+        return fin;
+    }
+
+    /**
+     * 输入流转换为输出流
+     *
+     * @param is 输入流
+     * @return 输出流
+     */
+    public static ByteArrayOutputStream convertInputStream(InputStream is) {
+        final byte[] by = new byte[1024];
+        ByteArrayOutputStream data = new ByteArrayOutputStream();
+        try {
+            // 将内容读取内存中
+            int len;
+            while ((len = is.read(by)) != -1) {
+                data.write(by, 0, len);
+            }
+        } catch (IOException e) {
+            log.error("convertInputStream IO Exception", e);
+        }
+        return data;
+    }
+
+    /**
+     * 文件后缀
+     *
+     * @param fileName 文件名或者文件路径
+     * @return 后缀类型
+     */
+    public static String getFileSuffix(String fileName) {
+        if (fileName == null) {
+            return null;
+        }
+        return fileName.substring(fileName.lastIndexOf("."));
+    }
+
+}