Browse Source

feat 主流云存储均以支持

1 month ago
parent
commit
cc0598b01d
15 changed files with 720 additions and 4 deletions
  1. 57 0
      edu-travel-common/edu-travel-common-upload/pom.xml
  2. 40 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/cos/TencentCosClient.java
  3. 45 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/cos/TencentCosUtils.java
  4. 27 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/cos/property/CosProperties.java
  5. 23 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/minio/CloudMinioClient.java
  6. 228 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/minio/CloudMinioUtils.java
  7. 26 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/minio/property/MinioProperties.java
  8. 20 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/obs/HuaweiOBSClient.java
  9. 116 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/obs/HuaweiOBSUtils.java
  10. 26 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/obs/property/ObsProperties.java
  11. 24 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/oss/AlibabaOSSClient.java
  12. 36 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/oss/AlibabaOSSUtils.java
  13. 26 0
      edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/oss/property/CloudOssProperty.java
  14. 1 0
      edu-travel-common/pom.xml
  15. 25 4
      pom.xml

+ 57 - 0
edu-travel-common/edu-travel-common-upload/pom.xml

@@ -0,0 +1,57 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>edu.travel</groupId>
+        <artifactId>edu-travel-common</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>edu-travel-common-upload</artifactId>
+    <packaging>jar</packaging>
+
+    <name>edu-travel-common-upload</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.huaweicloud</groupId>
+            <artifactId>esdk-obs-java</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.qcloud</groupId>
+            <artifactId>cos_api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

+ 40 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/cos/TencentCosClient.java

@@ -0,0 +1,40 @@
+package edu.travel.upload.cos;
+
+
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.region.Region;
+import edu.travel.upload.cos.property.CosProperties;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnClass(COSClient.class)
+public class TencentCosClient {
+    @Autowired
+    private CosProperties cosProperties;
+    private static PoolingHttpClientConnectionManager connectionManager;
+    public static void initializeConnectionManager() {
+        // 在这里初始化连接池
+        connectionManager = createConnectionManager();
+    }
+
+    private static PoolingHttpClientConnectionManager createConnectionManager() {
+        // 创建并配置连接池
+        return new PoolingHttpClientConnectionManager();
+    }
+
+    @Bean
+    public COSClient getCosClient() {
+        initializeConnectionManager();
+        COSCredentials cred = new BasicCOSCredentials(cosProperties.getAccessKey(), cosProperties.getSecretKey());
+        ClientConfig clientConfig = new ClientConfig(new Region(cosProperties.getRegionName()));
+        COSClient cosClient = new COSClient(cred, clientConfig);
+        return cosClient;
+    }
+}

+ 45 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/cos/TencentCosUtils.java

@@ -0,0 +1,45 @@
+package edu.travel.upload.cos;
+
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.model.PutObjectRequest;
+import com.qcloud.cos.transfer.TransferManager;
+import com.qcloud.cos.transfer.Upload;
+import edu.travel.upload.cos.property.CosProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+
+@Configuration
+@ConditionalOnClass(COSClient.class)
+public class TencentCosUtils {
+    @Autowired
+    private CosProperties cosProperties;
+    @Autowired
+    private COSClient cosClient;
+
+    /**
+     * 上传文件到COS
+     *
+     * @param inputStream 流
+     * @param key 文件名称
+     * @return
+     */
+    public  String uploadFileToCOS(InputStream inputStream, String key) throws InterruptedException, IOException, NoSuchAlgorithmException, KeyStoreException {
+        // 每次上传前重新初始化连接池
+        PutObjectRequest putObjectRequest = new PutObjectRequest(cosProperties.getBucketName(), key, inputStream, null);
+        TransferManager transferManager = new TransferManager(cosClient);
+        try {
+            Upload upload = transferManager.upload(putObjectRequest);
+            upload.waitForCompletion(); // 等待上传完成
+            String filePath = cosProperties.getBaseUrl() + "/" + key;
+            return filePath;
+        } finally {
+//            cosClient.shutdown(); // 关闭 COS 客户端
+        }
+    }
+}

+ 27 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/cos/property/CosProperties.java

@@ -0,0 +1,27 @@
+package edu.travel.upload.cos.property;
+
+
+import com.qcloud.cos.COSClient;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Component
+@ConfigurationProperties(prefix = "tencent.cos")
+@ConditionalOnClass(COSClient.class)
+public class CosProperties {
+   private String baseUrl;
+   private String  accessKey;
+   private String  secretKey;
+   private String  regionName;
+   private String  bucketName;
+   private String  folderPrefix;
+}

+ 23 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/minio/CloudMinioClient.java

@@ -0,0 +1,23 @@
+package edu.travel.upload.minio;
+
+import edu.travel.upload.minio.property.MinioProperties;
+import io.minio.MinioClient;
+import io.minio.errors.InvalidEndpointException;
+import io.minio.errors.InvalidPortException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnClass(MinioClient.class)
+public class CloudMinioClient {
+    @Autowired
+    public MinioProperties minioProperties;
+
+    @Bean
+    public MinioClient minioClient() throws InvalidPortException, InvalidEndpointException {
+        MinioClient minioClient = new MinioClient(minioProperties.getHost(), minioProperties.getAccessKey(), minioProperties.getSecretKey());
+        return minioClient;
+    }
+}

+ 228 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/minio/CloudMinioUtils.java

@@ -0,0 +1,228 @@
+package edu.travel.upload.minio;
+
+import edu.travel.upload.minio.property.MinioProperties;
+import io.minio.MinioClient;
+import io.minio.ObjectStat;
+import io.minio.PutObjectOptions;
+import io.minio.Result;
+import io.minio.messages.Bucket;
+import io.minio.messages.Item;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.util.UriUtils;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+@Configuration
+@ConditionalOnClass(MinioClient.class)
+public class CloudMinioUtils {
+    @Autowired
+    private MinioClient minioClient;
+    @Autowired
+    private MinioProperties minioProperties;
+    /**
+     * 上传
+     */
+    public String putObject(MultipartFile multipartFile) throws Exception {
+        // bucket 不存在,创建
+        if (!minioClient.bucketExists(minioProperties.getBucket())) {
+            minioClient.makeBucket(minioProperties.getBucket());
+        }
+        try (InputStream inputStream = multipartFile.getInputStream()) {
+            // 上传文件的名称
+            String fileName = multipartFile.getOriginalFilename();
+            // PutObjectOptions,上传配置(文件大小,内存中文件分片大小)
+            PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
+            // 文件的ContentType
+            putObjectOptions.setContentType(multipartFile.getContentType());
+            minioClient.putObject(minioProperties.getBucket(), fileName, inputStream, putObjectOptions);
+            // 返回访问路径
+            return minioProperties.getUrl() + UriUtils.encode(fileName, StandardCharsets.UTF_8);
+        }
+    }
+    /**
+     * 文件下载
+     */
+    public void download(String fileName, HttpServletResponse response){
+        // 从链接中得到文件名
+        InputStream inputStream;
+        try {
+
+            ObjectStat stat = minioClient.statObject(minioProperties.getBucket(), fileName);
+            inputStream = minioClient.getObject(minioProperties.getBucket(), fileName);
+            response.setContentType(stat.contentType());
+            response.setCharacterEncoding("UTF-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = inputStream.read(buffer)) > 0) {
+                response.getOutputStream().write(buffer, 0, length);
+            }
+            inputStream.close();
+        } catch (Exception e){
+            e.printStackTrace();
+            System.out.println("有异常:" + e);
+        }
+    }
+    /**
+     * 列出所有存储桶名称
+     *
+     * @return
+     * @throws Exception
+     */
+    public List<String> listBucketNames()
+            throws Exception {
+        List<Bucket> bucketList = listBuckets();
+        List<String> bucketListName = new ArrayList<>();
+        for (Bucket bucket : bucketList) {
+            bucketListName.add(bucket.name());
+        }
+        return bucketListName;
+    }
+
+    /**
+     * 查看所有桶
+     *
+     * @return
+     * @throws Exception
+     */
+    public List<Bucket> listBuckets()
+            throws Exception {
+        return minioClient.listBuckets();
+    }
+    /**
+     * 检查存储桶是否存在
+     *
+     * @param bucketName
+     * @return
+     * @throws Exception
+     */
+    public boolean bucketExists(String bucketName) throws Exception {
+        boolean flag = minioClient.bucketExists(bucketName);
+        if (flag) {
+            return true;
+        }
+        return false;
+    }
+    /**
+     * 创建存储桶
+     *
+     * @param bucketName
+     * @return
+     * @throws Exception
+     */
+    public boolean makeBucket(String bucketName)
+            throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (!flag) {
+            minioClient.makeBucket(bucketName);
+            return true;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * 删除桶
+     *
+     * @param bucketName
+     * @return
+     * @throws Exception
+     */
+    public boolean removeBucket(String bucketName)
+            throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            Iterable<Result<Item>> myObjects = listObjects(bucketName);
+            for (Result<Item> result : myObjects) {
+                Item item = result.get();
+                // 有对象文件,则删除失败
+                if (item.size() > 0) {
+                    return false;
+                }
+            }
+            // 删除存储桶,注意,只有存储桶为空时才能删除成功。
+            minioClient.removeBucket(bucketName);
+            flag = bucketExists(bucketName);
+            if (!flag) {
+                return true;
+            }
+        }
+        return false;
+    }
+    /**
+     * 列出存储桶中的所有对象
+     *
+     * @param bucketName 存储桶名称
+     * @return
+     * @throws Exception
+     */
+    public Iterable<Result<Item>> listObjects(String bucketName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            return minioClient.listObjects(bucketName);
+        }
+        return null;
+    }
+    /**
+     * 列出存储桶中的所有对象名称
+     *
+     * @param bucketName 存储桶名称
+     * @return
+     * @throws Exception
+     */
+    public List<String> listObjectNames(String bucketName) throws Exception {
+        List<String> listObjectNames = new ArrayList<>();
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            Iterable<Result<Item>> myObjects = listObjects(bucketName);
+            for (Result<Item> result : myObjects) {
+                Item item = result.get();
+                listObjectNames.add(item.objectName());
+            }
+        }
+        return listObjectNames;
+    }
+    /**
+     * 删除一个对象
+     *
+     * @param bucketName 存储桶名称
+     * @param objectName 存储桶里的对象名称
+     * @throws Exception
+     */
+    public boolean removeObject(String bucketName, String objectName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            List<String> objectList = listObjectNames(bucketName);
+            for (String s : objectList) {
+                if(s.equals(objectName)){
+                    minioClient.removeObject(bucketName, objectName);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    /**
+     * 文件访问路径
+     *
+     * @param bucketName 存储桶名称
+     * @param objectName 存储桶里的对象名称
+     * @return
+     * @throws Exception
+     */
+    public String getObjectUrl(String bucketName, String objectName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        String url = "";
+        if (flag) {
+            url = minioClient.getObjectUrl(bucketName, objectName);
+        }
+        return url;
+    }
+
+}

+ 26 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/minio/property/MinioProperties.java

@@ -0,0 +1,26 @@
+package edu.travel.upload.minio.property;
+
+import io.minio.MinioClient;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@ConditionalOnClass(MinioClient.class)
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Component
+@ConfigurationProperties(prefix = "minio")
+public class MinioProperties {
+    private String bucket;
+    private String host;
+    private String url;
+    private String accessKey;
+    private String secretKey;
+
+}

+ 20 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/obs/HuaweiOBSClient.java

@@ -0,0 +1,20 @@
+package edu.travel.upload.obs;
+
+import com.obs.services.ObsClient;
+import edu.travel.upload.obs.property.ObsProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConditionalOnClass(ObsClient.class)
+public class HuaweiOBSClient {
+    @Autowired
+    private ObsProperties obsProperties;
+    @Bean
+    public ObsClient obsClient() {
+      ObsClient  obsClient = new ObsClient(obsProperties.getAccessKey(), obsProperties.getSecretAccessKey(),obsProperties.getEndpoint());
+      return obsClient;
+    }
+}

+ 116 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/obs/HuaweiOBSUtils.java

@@ -0,0 +1,116 @@
+package edu.travel.upload.obs;
+
+import com.obs.services.ObsClient;
+import com.obs.services.exception.ObsException;
+import com.obs.services.internal.ServiceException;
+import com.obs.services.model.*;
+import edu.travel.upload.obs.property.ObsProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.stereotype.Component;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+import java.util.Optional;
+
+@Component
+@ConditionalOnClass(ObsClient.class)
+public class HuaweiOBSUtils {
+    Logger log = LoggerFactory.getLogger(HuaweiOBSUtils.class);
+    @Autowired
+    private ObsClient obsClient;
+    @Autowired
+    private ObsProperties obsProperties;
+    //注意这里传进来的参数是处理后的图片 base64 参数,处理方法只需要调用 api,这里不做过多解释,可以上网查询转换方法,另外是指定的文件名称和bucket名称,上传后的文件将是以该 fileName 存在于该bucket 内
+    //此方法是用于上传文件,内部调用了 obs 的含有 MD5 参数校验的api方法
+    public void uploadPic(String base64, String fileName) {
+        byte[] bytes = Base64.getDecoder().decode(base64);
+        ObjectMetadata meta = new ObjectMetadata();
+        // 设置MD5校验。
+        String md5 = toBase64String(calculateMd5(bytes));
+        meta.setContentMd5(md5);
+        try (InputStream inputStream = new ByteArrayInputStream(bytes)) {
+            PutObjectResult result = obsClient.putObject(obsProperties.getBucketName(), fileName, inputStream,meta);
+        } catch (Exception e) {
+            log.error("Upload failed: ", e);
+        }
+    }
+
+    // 计算 MD5 值的方法
+    private static byte[] calculateMd5(byte[] data) {
+        try {
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            return md.digest(data);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("MD5 algorithm not found.", e);
+        }
+    }
+
+    // 将字节数组转换为 Base64 编码的字符串
+    private static String toBase64String(byte[] bytes) {
+        return Base64.getEncoder().encodeToString(bytes);
+    }
+
+    //该方法是用于检查bucket 内是否有指定文件,内部调用了 obs 的获取文件方法
+    public Boolean checkExist(String fileName,String bucketName) {
+        ObsObject object = null;
+        InputStream inputStream = null;
+        try {
+            object = obsClient.getObject(bucketName, fileName);
+            inputStream = object.getObjectContent();
+            if (inputStream != null) {
+                return true;
+            }
+        } catch (Exception e) {
+            log.error("请求异常:{}", fileName, e);
+            return false;
+        } finally {
+            // 确保关闭 InputStream
+            try {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+            } catch (IOException e) {
+                log.error("关闭 InputStream 异常", e);
+            }
+        }
+        return false;
+    }
+
+
+    //该方法是用于获取指定时间内的文件下载链接
+    public String getPicViewUrlByInternal(String fileName) {
+        Boolean aBoolean = checkExist(fileName,obsProperties.getBucketName());
+        if (!aBoolean) {
+            return null;
+        }
+        // 生成以GET方法访问的签名URL,访客可以直接通过浏览器访问相关内容。
+        String url = generatePresignedUrl(obsProperties.getExpiration(), fileName,obsProperties.getBucketName());
+        return url;
+    }
+
+    private  String generatePresignedUrl(Long expire,String fileName,String bucketName) {
+        TemporarySignatureResponse response = null;
+        try {
+            // URL有效期,3600秒
+            //long expireSeconds = 3600L;
+            TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, expire);
+            request.setBucketName(bucketName);
+            request.setObjectKey(fileName);
+            response = obsClient.createTemporarySignature(request);
+        } catch (ObsException e) {
+            log.error("get obs failed :{}", e.getMessage());
+            throw new ServiceException(e.getMessage());
+        }
+        return Optional.ofNullable(response)
+                .map(TemporarySignatureResponse::getSignedUrl)
+                .orElse(null);
+    }
+
+}

+ 26 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/obs/property/ObsProperties.java

@@ -0,0 +1,26 @@
+package edu.travel.upload.obs.property;
+
+import com.obs.services.ObsClient;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Component
+@ConfigurationProperties(prefix = "huawei.obs")
+@ConditionalOnClass(ObsClient.class)
+public class ObsProperties {
+ 
+    private String endpoint;
+    private String accessKey;
+    private String secretAccessKey;
+    private String bucketName;
+    private Long expiration;
+}

+ 24 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/oss/AlibabaOSSClient.java

@@ -0,0 +1,24 @@
+package edu.travel.upload.oss;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import edu.travel.upload.oss.property.CloudOssProperty;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnClass(OSS.class)
+public class AlibabaOSSClient {
+    @Autowired
+    private CloudOssProperty cloudOssProperty;
+
+    @Bean
+    public OSS ossClient() {
+        OSS ossClient = new OSSClientBuilder().build(cloudOssProperty.getEndpoint(), cloudOssProperty.getAccessKeyId(), cloudOssProperty.getAccessKeySecret());
+        return ossClient;
+    }
+
+}

+ 36 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/oss/AlibabaOSSUtils.java

@@ -0,0 +1,36 @@
+package edu.travel.upload.oss;
+
+import com.aliyun.oss.OSS;
+import edu.travel.upload.obs.HuaweiOBSUtils;
+import edu.travel.upload.oss.property.CloudOssProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.stereotype.Component;
+
+import java.io.InputStream;
+import java.util.UUID;
+
+@Component
+@ConditionalOnClass(OSS.class)
+public class AlibabaOSSUtils {
+    Logger log = LoggerFactory.getLogger(AlibabaOSSUtils.class);
+
+    @Autowired
+    private OSS ossClient;
+    @Autowired
+    private CloudOssProperty cloudOssProperty;
+
+    public String uploadToOss(InputStream inputStream, String originalFilename){
+        // 生成唯一文件名
+        String filename = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
+        // 上传文件
+        ossClient.putObject(cloudOssProperty.getBucketName(), filename, inputStream);
+        // 返回文件的URL
+        return "https://" + cloudOssProperty.getBucketName() + "." + cloudOssProperty.getEndpoint() + "/" + filename;
+    }
+
+
+
+}

+ 26 - 0
edu-travel-common/edu-travel-common-upload/src/main/java/edu/travel/upload/oss/property/CloudOssProperty.java

@@ -0,0 +1,26 @@
+package edu.travel.upload.oss.property;
+
+import com.aliyun.oss.OSS;
+import com.obs.services.ObsClient;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Component
+@ConfigurationProperties(prefix = "alibaba.obs")
+@ConditionalOnClass(OSS.class)
+public class CloudOssProperty {
+    private String endpoint;
+    private String accessKeyId;
+    private String accessKeySecret;
+    private String bucketName;
+
+}

+ 1 - 0
edu-travel-common/pom.xml

@@ -22,6 +22,7 @@
         <module>edu-travel-common-util</module>
         <module>edu-travel-common-openfeign</module>
         <module>edu-travel-common-cache</module>
+        <module>edu-travel-common-upload</module>
     </modules>
 
     <properties>

+ 25 - 4
pom.xml

@@ -38,14 +38,35 @@
     <bootstrap.version>4.1.3</bootstrap.version>
     <pg.version>42.6.0</pg.version>
     <sharding.sphere.version>5.1.0</sharding.sphere.version>
-
+    <obs.version>3.20.6.1</obs.version>
+    <oss.version>3.10.2</oss.version>
+    <cos.version>5.6.54</cos.version>
+    <minio.version>7.0.2</minio.version>
   </properties>
   <dependencyManagement>
+
     <dependencies>
       <dependency>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-starter-validation</artifactId>
-        <version>2.3.12.RELEASE</version>
+        <groupId>io.minio</groupId>
+        <artifactId>minio</artifactId>
+        <version>${minio.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>com.aliyun.oss</groupId>
+        <artifactId>aliyun-sdk-oss</artifactId>
+        <version>${oss.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>com.qcloud</groupId>
+        <artifactId>cos_api</artifactId>
+        <version>${cos.version}</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>com.huaweicloud</groupId>
+        <artifactId>esdk-obs-java</artifactId>
+        <version>${obs.version}</version>
       </dependency>
 
       <dependency>