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

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

最近因為專案中需要儲存很多的圖片,不想儲存到伺服器上,因此就直接選用阿里雲的物件服務(`Object Storage Service`,簡稱 OSS)來進行儲存,本文將介紹 Spring Boot 整合 OSS 的一個完整過程。 那麼 OSS 是什麼呢? 簡而言之,OSS 是一種海量、安全、低成本、高可靠的雲端儲存服務。 關於 OSS 的知識就不再這裡贅述了,大家可以自行學習下。 ## 開通 OSS 首先需要在阿里雲控制檯開通 OSS,然後需要建立儲存空間(Bucket),我這裡命名為 `wupx-img`。 ![建立 Bucket](https://img-blog.csdnimg.cn/20200712175636178.png) > 如果之前沒有建立過 AccessKey,滑鼠移到右上角的賬號後點擊 AccessKey 管理,然後建立就可以了。 > > 或者直接輸入 https://ak-console.aliyun.com/#/ 來進行金鑰的建立和檢視。 ![AccessKey 管理](https://img-blog.csdnimg.cn/20200712180550514.png) 準備工作做好後,就開始進行專案實戰吧! ## Spring Boot 整合 OSS Spring Boot 整合 OSS 主要分為以下三步: 1. 加入 OSS 依賴 2. 配置 OSS 3. 演示 OSS 基本操作 ### 加入依賴 首先建立一個 Spring Boot 專案,然後在 `pom.xml` 加入如下依賴整合 OSS: ``` com.aliyun.oss
aliyun-sdk-oss 3.10.2
``` ### 建立 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` 類,然後注入 `ossClient` 和 `ossConfiguration`。 #### 上傳檔案 首先來看下如何上傳檔案,首先通過 UUID 生成檔名,防止重複,再建立一個 `ObjectMetadata`,可以設定使用者自定義的元資料以及 HTTP 頭,比如內容長度,ETag 等,最後通過呼叫 `ossClient` 的 `putObject` 方法來完成檔案上傳,並返回檔名,具體程式碼如下所示: ``` 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` 層,呼叫上傳檔案介面後,在檔案管理中可以看到檔案已經上傳成功了: ![上傳檔案](https://img-blog.csdnimg.cn/20200713222546198.png) #### 獲取檔案列表 可以通過 `ListObjectsRequest` 構建請求引數,比如設定 Bucket 名稱和列舉檔案的最大個數,然後呼叫 `ossClient` 的 `listObjects` 方法就可以獲取到 `objectListing`,再獲取檔案的元資訊,最後將檔名稱返回,具體程式碼如下: ``` public List listObjects() { ListObjectsRequest listObjectsRequest = new ListObjectsRequest(ossConfiguration.getBucketName()).withMaxKeys(200); ObjectListing objectListing = ossClient.listObjects(listObjectsRequest); List objectSummaries = objectListing.getObjectSummaries(); return objectSummaries.stream().map(OSSObjectSummary::getKey).collect(Collectors.toList()); } ``` #### 判斷檔案是否存在 判斷檔案是否存在,直接通過 `ossClient` 的 `doesObjectExist` 方法就可以進行判斷,傳入的引數為 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 名稱和檔名稱呼叫 `ossClient` 的 `getObject` 方法獲取 `ossObject`,`ossObject` 包含檔案所在的儲存空間名稱、檔名稱、檔案元資訊以及一個輸入流,然後呼叫 `ossObject` 的 `getObjectContent` 方法獲取輸入流,然後進行檔案的下載,具體程式碼如下: ``` 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); } } ``` ![](https://img-blog.csdnimg.cn/20200713225007225.png) #### 刪除檔案 刪除檔案也比較簡單,直接呼叫 `deleteObject` 方法,傳入對應的 Bucket 名稱和檔名稱即可,具體程式碼如下: ``` public void deleteFile(String fileName) { try { ossClient.deleteObject(ossConfiguration.getBucketName(), fileName); } catch (Exception e) { log.error("Error occurred: {}", e.getMessage(), e); } } ``` #### 檢視 URL 獲取檔案的訪問地址可以呼叫 `ossClient` 的 `generatePresignedUrl`,在呼叫的時候還需要設定過期時間,具體程式碼如下: ``` 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 就可以訪問圖片,效果如下: ![](https://img-blog.csdnimg.cn/20200713233152781.png) 到此為止,OSS 的基本操作就簡單介紹完了,大家可以多動手試試,不會的可以看下官方的幫助文件。 ##### 跨域規則 阿里雲 OSS 解決請求跨越問題:進入對應的 Bucket,然後依次點選許可權管理->跨越設定->建立規則,然後填寫上對應的規則,具體如下圖所示: ![跨域規則](https://img-blog.csdnimg.cn/20200713220728125.png) # 總結 本文的完整程式碼在 `https://github.com/wupeixuan/SpringBoot-Learn` 的 `oss` 目錄下。 Spring Boot 結合 OSS 還是比較簡單的,大家可以下載專案原始碼,自己在本地執行除錯這個專案,更好地理解如何在 Spring Boot 中構建基於 OSS 的應用。 **最好的關係就是互相成就**,大家的**點贊、在看、分享、留言**就是我創作的最大動力。 > 參考 > > https://github.com/wupeixuan/SpringBoot-Learn > > https://help.aliyun.com/document_detail/32