chao 3 лет назад
Родитель
Сommit
68eab2544b

+ 6 - 1
pom.xml

@@ -104,7 +104,12 @@
             <artifactId>fastdfs-client</artifactId>
             <artifactId>fastdfs-client</artifactId>
             <version>1.27.2</version>
             <version>1.27.2</version>
         </dependency>
         </dependency>
-
+        <!--对象存储oss-->
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.12.0</version>
+        </dependency>
         <!-- https://mvnrepository.com/artifact/org.apache.rocketmq/rocketmq-spring-boot-starter -->
         <!-- https://mvnrepository.com/artifact/org.apache.rocketmq/rocketmq-spring-boot-starter -->
         <!-- RocketMQ starter -->
         <!-- RocketMQ starter -->
         <dependency>
         <dependency>

+ 39 - 4
src/main/java/com/caimei365/tools/controller/UploadApi.java

@@ -8,11 +8,14 @@ import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpHeaders;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
 
 
+import java.util.Map;
+
 /**
 /**
  * Description
  * Description
  *
  *
@@ -27,13 +30,45 @@ import org.springframework.web.multipart.MultipartFile;
 public class UploadApi {
 public class UploadApi {
 
 
     private final UploadService uploadService;
     private final UploadService uploadService;
+
+    /**
+     * 上传文件至oss服务器
+     */
+    @ApiOperation("上传文件至oss服务器(旧:/file/upload)")
+    @ApiImplicitParam(required = true, name = "file", value = "文件")
+    @PostMapping("/file/upload/oss")
+    public ResponseJson<Map<String, Object>> uploadFileToOss(MultipartFile file, @RequestHeader HttpHeaders headers) {
+        return uploadService.uploadFileToOss(file, headers);
+    }
+
     /**
     /**
-     * 图片上传
+     * 删除oss服务器的文件
+     */
+    @ApiOperation("删除oss服务器的文件(旧:/file/delete)")
+    @ApiImplicitParam(required = true, name = "ossName", value = "OSS文件名")
+    @PostMapping("/file/delete/oss")
+    public ResponseJson<Void> deleteFileFromOss(String ossName) {
+        return uploadService.deleteFileFromOss(ossName);
+    }
+
+    /**
+     * FastDFS图片上传
      */
      */
     @ApiOperation("图片上传(旧:/formData/MultiPictareaddData)")
     @ApiOperation("图片上传(旧:/formData/MultiPictareaddData)")
     @ApiImplicitParam(required = true, name = "file", value = "图片")
     @ApiImplicitParam(required = true, name = "file", value = "图片")
-    @RequestMapping("/upload/image")
-    public ResponseJson<String> bulkImageUpload(MultipartFile[] file, @RequestHeader HttpHeaders headers) {
-        return uploadService.bulkImageUpload(file, headers);
+    @RequestMapping("/image/upload/multi")
+    public ResponseJson<String> multiImageUpload(MultipartFile[] file, @RequestHeader HttpHeaders headers) {
+        return uploadService.multiImageUpload(file, headers);
     }
     }
+
+    /**
+     * 图片上传(ckeditor5富文本编辑器上传图片用)
+     */
+    @ApiOperation("ckeditor5图片上传(旧:/formData/ckeditorImage)")
+    @ApiImplicitParam(required = true, name = "upload", value = "图片")
+    @RequestMapping("/image/upload/ckeditor")
+    public ResponseJson<String> ckeditorImageUpload(MultipartFile upload, @RequestHeader HttpHeaders headers) {
+        return uploadService.ckeditorImageUpload(upload, headers);
+    }
+
 }
 }

+ 19 - 2
src/main/java/com/caimei365/tools/service/UploadService.java

@@ -4,6 +4,8 @@ import com.caimei365.tools.model.ResponseJson;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpHeaders;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
 
 
+import java.util.Map;
+
 /**
 /**
  * Description
  * Description
  *
  *
@@ -12,7 +14,22 @@ import org.springframework.web.multipart.MultipartFile;
  */
  */
 public interface UploadService {
 public interface UploadService {
     /**
     /**
-     * 图片上传
+     * 上传文件至oss服务器
+     */
+    ResponseJson<Map<String, Object>> uploadFileToOss(MultipartFile file, HttpHeaders headers);
+
+    /**
+     * 删除oss服务器的文件
+     */
+    ResponseJson<Void> deleteFileFromOss(String ossName);
+
+    /**
+     * FastDFS图片上传
+     */
+    ResponseJson<String> multiImageUpload(MultipartFile[] file, HttpHeaders headers);
+
+    /**
+     * 图片上传(ckeditor5富文本编辑器上传图片用)
      */
      */
-    ResponseJson<String> bulkImageUpload(MultipartFile[] file, HttpHeaders headers);
+    ResponseJson<String> ckeditorImageUpload(MultipartFile upload, HttpHeaders headers);
 }
 }

+ 82 - 4
src/main/java/com/caimei365/tools/service/impl/UploadServiceImpl.java

@@ -3,7 +3,9 @@ package com.caimei365.tools.service.impl;
 import com.caimei365.tools.model.ResponseJson;
 import com.caimei365.tools.model.ResponseJson;
 import com.caimei365.tools.service.UploadService;
 import com.caimei365.tools.service.UploadService;
 import com.caimei365.tools.utils.FastDfsUtil;
 import com.caimei365.tools.utils.FastDfsUtil;
+import com.caimei365.tools.utils.OssUtils;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpHeaders;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -12,6 +14,8 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import java.io.File;
 import java.io.File;
 import java.io.IOException;
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.UUID;
 import java.util.UUID;
 
 
 /**
 /**
@@ -31,10 +35,61 @@ public class UploadServiceImpl implements UploadService {
     private FastDfsUtil fastDfsUtil;
     private FastDfsUtil fastDfsUtil;
 
 
     /**
     /**
-     * 图片上传
+     * 上传文件至oss服务器
+     *
+     * @param file
+     * @param headers
      */
      */
     @Override
     @Override
-    public ResponseJson<String> bulkImageUpload(MultipartFile[] file, HttpHeaders headers){
+    public ResponseJson<Map<String, Object>> uploadFileToOss(MultipartFile file, HttpHeaders headers) {
+        // 打印IP
+        String ip = headers.getFirst("X-CLIENT-IP");
+        log.info("【OSS文件上传】 X-CLIENT-IP : " + ip);
+        Map<String, Object> map = new HashMap<>(3);
+        String fileName = file.getOriginalFilename();
+        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
+        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
+        String filePath = uuid + "." + fileType;
+        String contentType = OssUtils.getContentType(fileName);
+        try {
+            //保存本地
+            File localFile = OssUtils.ossUpload(file);
+            String url = "";
+            log.info("【OSS文件上传】>>>>>>>>>>>>>>>>默认路径:" + localFile.getAbsolutePath());
+            //上传oss
+            url = OssUtils.ossUpload(filePath, localFile, contentType);
+            //删除本地文件
+            OssUtils.deleteFile(localFile);
+            map.put("fileName", fileName);
+            map.put("ossName", filePath);
+            map.put("url", url);
+        } catch (IOException e) {
+            log.error("【OSS文件上传】>>>>>>>>>>>>>>>>上传失败:" + e);
+            return ResponseJson.error("上传文件失败!", null);
+        }
+        return ResponseJson.success(map);
+    }
+
+    /**
+     * 删除oss服务器的文件
+     *
+     * @param ossName
+     */
+    @Override
+    public ResponseJson<Void> deleteFileFromOss(String ossName) {
+        if (StringUtils.isBlank(ossName)) {
+            return ResponseJson.error("参数异常", null);
+        }
+        //删除oss服务器上的文件
+        OssUtils.deleteSingleFile(ossName);
+        return ResponseJson.success(null);
+    }
+
+    /**
+     * FastDFS图片上传
+     */
+    @Override
+    public ResponseJson<String> multiImageUpload(MultipartFile[] file, HttpHeaders headers){
         // 打印IP
         // 打印IP
         String ip = headers.getFirst("X-CLIENT-IP");
         String ip = headers.getFirst("X-CLIENT-IP");
         log.info("【图片上传】 X-CLIENT-IP : " + ip);
         log.info("【图片上传】 X-CLIENT-IP : " + ip);
@@ -49,7 +104,30 @@ public class UploadServiceImpl implements UploadService {
                 return ResponseJson.success("上传成功", fileUrl.toString());
                 return ResponseJson.success("上传成功", fileUrl.toString());
             } catch (IOException e) {
             } catch (IOException e) {
                 log.error("【图片上传】>>>>>>>>>>>>>>>>上传失败:" + e);
                 log.error("【图片上传】>>>>>>>>>>>>>>>>上传失败:" + e);
-                return ResponseJson.error("请传入图片!",null);
+                return ResponseJson.error("图片上传失败!",null);
+            }
+        } else {
+            return ResponseJson.error("请传入图片!",null);
+        }
+    }
+
+    /**
+     * 图片上传(ckeditor5富文本编辑器上传图片用)
+     */
+    @Override
+    public ResponseJson<String> ckeditorImageUpload(MultipartFile upload, HttpHeaders headers) {
+        // 打印IP
+        String ip = headers.getFirst("X-CLIENT-IP");
+        log.info("【图片上传】 X-CLIENT-IP : " + ip);
+        if (upload != null) {
+            try {
+                String url = saveFile(upload);
+                StringBuilder fileUrl = new StringBuilder().append(imageDomain).append("/").append(url);
+                log.info("【图片上传】>>>>>>>>>>>>>>>>上传成功:" + fileUrl);
+                return ResponseJson.success("上传成功", fileUrl.toString());
+            } catch (IOException e) {
+                log.error("【图片上传】>>>>>>>>>>>>>>>>上传失败:" + e);
+                return ResponseJson.error("图片上传失败!",null);
             }
             }
         } else {
         } else {
             return ResponseJson.error("请传入图片!",null);
             return ResponseJson.error("请传入图片!",null);
@@ -57,7 +135,7 @@ public class UploadServiceImpl implements UploadService {
     }
     }
 
 
     /**
     /**
-     * 保存文件
+     * 保存文件到FastDFS
      */
      */
     private String saveFile(MultipartFile file) throws IOException {
     private String saveFile(MultipartFile file) throws IOException {
         String originalFilename = file.getOriginalFilename();
         String originalFilename = file.getOriginalFilename();

+ 209 - 0
src/main/java/com/caimei365/tools/utils/OssUtils.java

@@ -0,0 +1,209 @@
+package com.caimei365.tools.utils;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.model.GetObjectRequest;
+import com.aliyun.oss.model.ObjectMetadata;
+import com.aliyun.oss.model.UploadFileRequest;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.UUID;
+
+
+/**
+ * 文件的上传下载
+ *
+ * @author Administrator
+ */
+@Component
+public class OssUtils {
+    private static String endpoint;
+
+    @Value("${aliyunConfig.endpoint}")
+    public void setEndpoint(String endpoints) {
+        endpoint = endpoints;
+    }
+
+    private static String accessKeyId;
+
+    @Value("${aliyunConfig.accessKeyId}")
+    public void setAccessKeyId(String accessKeyIds) {
+        accessKeyId = accessKeyIds;
+    }
+
+    private static String accessKeySecret;
+
+    @Value("${aliyunConfig.accessKeySecret}")
+    public void setAccessKeySecret(String accessKeySecrets) {
+        accessKeySecret = accessKeySecrets;
+    }
+
+    private static String privateBucket;
+
+    @Value("${aliyunConfig.bucketName}")
+    public void setPrivateBucket(String bucketName) {
+        privateBucket = bucketName;
+    }
+
+    private static String active;
+
+    @Value("${spring.cloud.config.profile}")
+    public void setActive(String actives) {
+        active = actives;
+    }
+
+
+    public static String ossUpload(String fileName, File file, String contentType) {
+        String url = null;
+        try {
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+            ObjectMetadata meta = new ObjectMetadata();
+            meta.setContentType(contentType);
+            fileName = active + "/" + fileName;
+            UploadFileRequest uploadFileRequest = new UploadFileRequest(privateBucket, fileName);
+            // 指定上传的本地文件。
+            uploadFileRequest.setUploadFile(file.toString());
+            // 指定上传并发线程数,默认为1。
+            uploadFileRequest.setTaskNum(10);
+            // 指定上传的分片大小,范围为100KB~5GB,默认为文件大小/10000。
+            uploadFileRequest.setPartSize(1024 * 1024);
+            // 开启断点续传,默认关闭。
+            uploadFileRequest.setEnableCheckpoint(true);
+            uploadFileRequest.setCheckpointFile(file.getAbsolutePath() + "uploadFile.ucp");
+            // 文件的元数据。
+            uploadFileRequest.setObjectMetadata(meta);
+            // 设置上传成功回调,参数为Callback类型。
+            //uploadFileRequest.setCallback("<yourCallbackEvent>");
+            //断点续传上传。
+            ossClient.uploadFile(uploadFileRequest);
+            Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000);
+            url = ossClient.generatePresignedUrl(privateBucket, fileName, expiration).toString();
+            // 关闭OSSClient。
+            ossClient.shutdown();
+        } catch (Throwable e) {
+            e.printStackTrace();
+        }
+        return url;
+    }
+
+
+    /**
+     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
+     */
+    public static String getContentType(String fileName) {
+        String fileExtension = fileName.substring(fileName.lastIndexOf("."));
+        if (".bmp".equalsIgnoreCase(fileExtension)) {
+            return "image/bmp";
+        }
+        if (".gif".equalsIgnoreCase(fileExtension)) {
+            return "image/gif";
+        }
+        if (".jpeg".equalsIgnoreCase(fileExtension)) {
+            return "image/jpeg";
+        }
+        if (".jpg".equalsIgnoreCase(fileExtension)) {
+            return "image/jpg";
+        }
+        if (".png".equalsIgnoreCase(fileExtension)) {
+            return "image/png";
+        }
+        if (".html".equalsIgnoreCase(fileExtension)) {
+            return "text/html";
+        }
+        if (".txt".equalsIgnoreCase(fileExtension)) {
+            return "text/plain";
+        }
+        if (".vsd".equalsIgnoreCase(fileExtension)) {
+            return "application/vnd.visio";
+        }
+        if (".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) {
+            return "application/vnd.ms-powerpoint";
+        }
+        if (".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) {
+            return "application/msword";
+        }
+        if (".xml".equalsIgnoreCase(fileExtension)) {
+            return "text/xml";
+        }
+        if (".mp4".equalsIgnoreCase(fileExtension)) {
+            return "video/mp4";
+        }
+        if (".mp3".equalsIgnoreCase(fileExtension)) {
+            return "audio/mp3";
+        }
+        if (".pdf".equalsIgnoreCase(fileExtension)) {
+            return "application/pdf";
+        }
+        return "text/html";
+    }
+
+    public static void deleteFile(File... files) {
+        for (File file : files) {
+            //logger.info("File:[{}]",file.getAbsolutePath());
+            if (file.exists()) {
+                file.delete();
+            }
+        }
+    }
+
+    public static File ossUpload(MultipartFile file) throws IOException {
+        // 获取文件名
+        String fileName = file.getOriginalFilename();
+        // 获取文件后缀
+        String prefix = fileName.substring(fileName.lastIndexOf("."));
+        // 用uuid作为文件名,防止生成的临时文件重复
+        File excelFile = File.createTempFile(UUID.randomUUID().toString(), prefix);
+        // MultipartFile to File
+        file.transferTo(excelFile);
+        //程序结束时,删除临时文件
+        return excelFile;
+    }
+
+    /**
+     * 授权生成签名URL临时访问
+     *
+     * @param fileName 文件名称
+     */
+    public static String getOssUrl(String fileName) {
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        // 设置URL过期时间为1个小时
+        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000);
+        String url = ossClient.generatePresignedUrl(privateBucket, fileName, expiration).toString();
+        // 关闭OSSClient。
+        ossClient.shutdown();
+        return url;
+    }
+
+    /**
+     * oss单个文件删除
+     *
+     * @param fileName 文件名称或文件夹名称
+     */
+    public static void deleteSingleFile(String fileName) {
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        // 删除文件。如需删除文件夹,请将ObjectName设置为对应的文件夹名称。
+        // 如果文件夹非空,则需要将文件夹下的所有object删除后才能删除该文件夹。
+        fileName = active + "/" + fileName;
+        ossClient.deleteObject(privateBucket, fileName);
+        // 关闭OSSClient。
+        ossClient.shutdown();
+    }
+
+    /**
+     * oss单个文件下载
+     */
+    public static void downFile(String ossName, String fileName) {
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
+        ossClient.getObject(new GetObjectRequest(privateBucket, ossName), new File("./" + fileName));
+        // 关闭OSSClient。
+        ossClient.shutdown();
+    }
+}