1. 程式人生 > 實用技巧 >Spring Boot 整合阿里雲 OSS 進行檔案儲存

Spring Boot 整合阿里雲 OSS 進行檔案儲存

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

那麼 OSS 是什麼呢?

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

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

開通 OSS

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

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

或者直接輸入 https://ak-console.aliyun.com/#/ 來進行金鑰的建立和檢視。

準備工作做好後,就開始進行專案實戰吧!

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