Spring Boot 集成阿里雲 OSS 進行文件存儲


最近因為項目中需要存儲很多的圖片,不想存儲到服務器上,因此就直接選用阿里雲的對象服務(Object Storage Service,簡稱 OSS)來進行存儲,本文將介紹 Spring Boot 集成 OSS 的一個完整過程。

那么 OSS 是什么呢?

簡而言之,OSS 是一種海量、安全、低成本、高可靠的雲存儲服務。

關於 OSS 的知識就不再這里贅述了,大家可以自行學習下。

開通 OSS

首先需要在阿里雲控制台開通 OSS,然后需要創建存儲空間(Bucket),我這里命名為 wupx-img

創建 Bucket

如果之前沒有創建過 AccessKey,鼠標移到右上角的賬號后點擊 AccessKey 管理,然后創建就可以了。

或者直接輸入 https://ak-console.aliyun.com/#/ 來進行密鑰的創建和查看。

AccessKey 管理

准備工作做好后,就開始進行項目實戰吧!

Spring Boot 集成 OSS

Spring Boot 集成 OSS 主要分為以下三步:

  1. 加入 OSS 依賴
  2. 配置 OSS
  3. 演示 OSS 基本操作

加入依賴

首先創建一個 Spring Boot 項目,然后在 pom.xml 加入如下依賴集成 OSS:

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</version>
</dependency>

創建 OSS 配置

在配置文件 application.properties 中配置 OSS 的相關參數,具體內容如下:

#訪問OSS的域名
aliyun.endpoint=http://oss-cn-beijing.aliyuncs.com
aliyun.accessKeyId=yourAccessKeyId
aliyun.accessKeySecret=yourAccessKeySecret
#管理所存儲Object的存儲空間名稱
#aliyun.bucketName=yourBucketName
spring.servlet.multipart.max-request-size=10MB
spring.servlet.multipart.max-file-size=10MB

其中指定了 OSS 的訪問域名、密鑰以及存儲空間 Bucket 的名稱等。

然后在 config 包下創建 OSSConfiguration 類,會從配置文件中讀取到對應的參數,並且把 ossClient 單例化。

@Configuration
@Component
public class OSSConfiguration {

    private volatile static OSS ossClient;

    private volatile static OSSClientBuilder ossClientBuilder;

    private static String endpoint;

    private static String accessKeyId;

    private static String accessKeySecret;

    @Value("${aliyun.bucketName}")
    private String bucketName;

    @Value("${aliyun.endpoint}")
    public void setEndpoint(String endpoint) {
        OSSConfiguration.endpoint = endpoint;
    }

    @Value("${aliyun.accessKeyId}")
    public void setAccessKeyId(String accessKeyId) {
        OSSConfiguration.accessKeyId = accessKeyId;
    }

    @Value("${aliyun.accessKeySecret}")
    public void setAccessKeySecret(String accessKeySecret) {
        OSSConfiguration.accessKeySecret = accessKeySecret;
    }

    public String getBucketName() {
        return bucketName;
    }

    @Bean
    @Scope("prototype")
    public static OSS initOSSClient() {
        if (ossClient == null) {
            synchronized (OSSConfiguration.class) {
                if (ossClient == null) {
                    ossClient = initOSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
                }
            }
        }
        return ossClient;
    }

    public static OSSClientBuilder initOSSClientBuilder() {
        if (ossClientBuilder == null) {
            synchronized (OSSConfiguration.class) {
                if (ossClientBuilder == null) {
                    ossClientBuilder = new OSSClientBuilder();
                }
            }
        }
        return ossClientBuilder;
    }
}

服務類

在這里主要介紹 OSS 的上傳、下載、刪除、查看 URL 等簡單操作,在 service 包下創建 OSSService 類,然后注入 ossClientossConfiguration

上傳文件

首先來看下如何上傳文件,首先通過 UUID 生成文件名,防止重復,再創建一個 ObjectMetadata,可以設置用戶自定義的元數據以及 HTTP 頭,比如內容長度,ETag 等,最后通過調用 ossClientputObject 方法來完成文件上傳,並返回文件名,具體代碼如下所示:

public String uploadFile(MultipartFile file, String storagePath) {
    String fileName = "";
    try {
        fileName = UUID.randomUUID().toString();
        InputStream inputStream = file.getInputStream();
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(inputStream.available());
        objectMetadata.setCacheControl("no-cache");
        objectMetadata.setHeader("Pragma", "no-cache");
        objectMetadata.setContentType(file.getContentType());
        objectMetadata.setContentDisposition("inline;filename=" + fileName);
        fileName = storagePath + "/" + fileName;
        // 上傳文件
        ossClient.putObject(ossConfiguration.getBucketName(), fileName, inputStream, objectMetadata);
    } catch (IOException e) {
        log.error("Error occurred: {}", e.getMessage(), e);
    }
    return fileName;
}

編寫對應的 Controller 層,調用上傳文件接口后,在文件管理中可以看到文件已經上傳成功了:

上傳文件

獲取文件列表

可以通過 ListObjectsRequest 構建請求參數,比如設置 Bucket 名稱和列舉文件的最大個數,然后調用 ossClientlistObjects 方法就可以獲取到 objectListing,再獲取文件的元信息,最后將文件名稱返回,具體代碼如下:

public List<String> listObjects() {
    ListObjectsRequest listObjectsRequest = new ListObjectsRequest(ossConfiguration.getBucketName()).withMaxKeys(200);
    ObjectListing objectListing = ossClient.listObjects(listObjectsRequest);
    List<OSSObjectSummary> objectSummaries = objectListing.getObjectSummaries();
    return objectSummaries.stream().map(OSSObjectSummary::getKey).collect(Collectors.toList());
}

判斷文件是否存在

判斷文件是否存在,直接通過 ossClientdoesObjectExist 方法就可以進行判斷,傳入的參數為 Bucket 名稱和文件名稱,具體代碼如下:

public boolean doesObjectExist(String fileName) {
    try {
        if (Strings.isEmpty(fileName)) {
            log.error("文件名不能為空");
            return false;
        } else {
            return ossClient.doesObjectExist(ossConfiguration.getBucketName(), fileName);
        }
    } catch (OSSException | ClientException e) {
        e.printStackTrace();
    }
    return false;
}

下載文件

下載存儲在 OSS 的文件,首先需要傳入 Bucket 名稱和文件名稱調用 ossClientgetObject 方法獲取 ossObjectossObject 包含文件所在的存儲空間名稱、文件名稱、文件元信息以及一個輸入流,然后調用 ossObjectgetObjectContent 方法獲取輸入流,然后進行文件的下載,具體代碼如下:

public void exportFile(OutputStream os, String objectName) {
    OSSObject ossObject = ossClient.getObject(ossConfiguration.getBucketName(), objectName);
    // 讀取文件內容
    BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());
    BufferedOutputStream out = new BufferedOutputStream(os);
    byte[] buffer = new byte[1024];
    int lenght;
    try {
        while ((lenght = in.read(buffer)) != -1) {
            out.write(buffer, 0, lenght);
        }
        out.flush();
    } catch (IOException e) {
        log.error("Error occurred: {}", e.getMessage(), e);
    }
}

刪除文件

刪除文件也比較簡單,直接調用 deleteObject 方法,傳入對應的 Bucket 名稱和文件名稱即可,具體代碼如下:

public void deleteFile(String fileName) {
    try {
        ossClient.deleteObject(ossConfiguration.getBucketName(), fileName);
    } catch (Exception e) {
        log.error("Error occurred: {}", e.getMessage(), e);
    }
}

查看 URL

獲取文件的訪問地址可以調用 ossClientgeneratePresignedUrl,在調用的時候還需要設置過期時間,具體代碼如下:

public String getSingeNatureUrl(String filename, int expSeconds) {
    Date expiration = new Date(System.currentTimeMillis() + expSeconds * 1000);
    URL url = ossClient.generatePresignedUrl(ossConfiguration.getBucketName(), filename, expiration);
    if (url != null) {
        return url.toString();
    }
    return null;
}

通過調用接口即可返回文件對應的 url 地址,我們通過 url 就可以訪問圖片,效果如下:

到此為止,OSS 的基本操作就簡單介紹完了,大家可以多動手試試,不會的可以看下官方的幫助文檔。

跨域規則

阿里雲 OSS 解決請求跨越問題:進入對應的 Bucket,然后依次點擊權限管理->跨越設置->創建規則,然后填寫上對應的規則,具體如下圖所示:

跨域規則

總結

本文的完整代碼在 https://github.com/wupeixuan/SpringBoot-Learnoss 目錄下。

Spring Boot 結合 OSS 還是比較簡單的,大家可以下載項目源碼,自己在本地運行調試這個項目,更好地理解如何在 Spring Boot 中構建基於 OSS 的應用。

最好的關系就是互相成就,大家的點贊、在看、分享、留言就是我創作的最大動力。

參考

https://github.com/wupeixuan/SpringBoot-Learn

https://help.aliyun.com/document_detail/32008.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM