STS介紹
阿里雲STS (Security Token Service) 是為阿里雲賬號(或RAM用戶)提供短期訪問權限管理的雲服務。通過STS,您可以為聯盟用戶(您的本地賬號系統所管理的用戶)頒發一個自定義時效和訪問權限的訪問憑證。聯盟用戶可以使用STS短期訪問憑證直接調用阿里雲服務API,或登錄阿里雲管理控制台操作被授權訪問的資源。
訪問點
STS的默認訪問點地址是: https://sts.aliyuncs.com
,用戶必須使用https接入訪問點。
術語表
術語 | 中文 | 說明 |
---|---|---|
Federated identity | 聯盟用戶身份 | 聯盟用戶的身份認證由客戶自己管理 |
Policy | 訪問策略 | 用來描述授權策略的一種描述語言 |
Grantor | 授權者 | 授權令牌的頒發者(雲賬號或RAM用戶) |
Name | 被授權者 | 授權令牌的使用者(即聯盟用戶) |
https://help.aliyun.com/document_detail/28756.html?spm=a2c4g.11186623.2.9.4d4f412fzjwgui#reference-ong-5nv-xdb
授權訪問
使用STS進行臨時授權
OSS可以通過阿里雲STS (Security Token Service) 進行臨時授權訪問。阿里雲STS是為雲計算用戶提供臨時訪問令牌的Web服務。通過STS,您可以為第三方應用或子用戶(即用戶身份由您自己管理的用戶)頒發一個自定義時效和權限的訪問憑證。STS更詳細的解釋請參見STS介紹。
STS的優勢如下:
- 您無需透露您的長期密鑰(AccessKey)給第三方應用,只需生成一個訪問令牌並將令牌交給第三方應用。您可以自定義這個令牌的訪問權限及有效期限。
- 您無需關心權限撤銷問題,訪問令牌過期后自動失效。
使用STS訪問OSS的流程請參見開發指南中的RAM和STS應用場景實踐。
使用簽名URL上傳文件
以下代碼用於使用簽名URL上傳文件:
// Endpoint以杭州為例,其它Region請按實際情況填寫。 String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; // 阿里雲主賬號AccessKey擁有所有API的訪問權限,風險很高。強烈建議您創建並使用RAM賬號進行API訪問或日常運維,請登錄 https://ram.console.aliyun.com 創建RAM賬號。 String accessKeyId = "<yourAccessKeyId>"; String accessKeySecret = "<yourAccessKeySecret>"; String bucketName = "<yourBucketName>"; String objectName = "<yourObjectName>"; // 創建OSSClient實例。 OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); // 生成簽名URL。 Date expiration = DateUtil.parseRfc822Date("Thu, 19 Mar 2019 18:00:00 GMT"); GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT); // 設置過期時間。 request.setExpiration(expiration); // 設置Content-Type。 request.setContentType("application/octet-stream"); // 添加用戶自定義元信息。 request.addUserMetadata("author", "aliy"); // 生成簽名URL(HTTP PUT請求)。 URL signedUrl = ossClient.generatePresignedUrl(request); System.out.println("signed url for putObject: " + signedUrl); // 使用簽名URL發送請求。 File f = new File("<yourLocalFile>"); FileInputStream fin = new FileInputStream(f); // 添加PutObject請求頭。 Map<String, String> customHeaders = new HashMap<String, String>(); customHeaders.put("Content-Type", "application/octet-stream"); customHeaders.put("x-oss-meta-author", "aliy"); PutObjectResult result = ossClient.putObject(signedUrl, fin, f.length(), customHeaders); // 關閉OSSClient。 ossClient.shutdown();
https://help.aliyun.com/document_detail/32016.html
錯誤碼大全
https://error-center.aliyun.com/status/product/Oss
// endpoint以杭州為例,其它region請按實際情況填寫 String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; // accessKey請登錄https://ak-console.aliyun.com/#/查看 String accessKeyId = "<yourAccessKeyId>"; String accessKeySecret = "<yourAccessKeySecret>"; String content = "Hello OSS"; // 創建OSSClient實例 OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); AppendObjectRequest appendObjectRequest = new AppendObjectRequest("<yourBucketName>", "<yourKey>", new ByteArrayInputStream(content.getBytes())); // 第一次追加 appendObjectRequest.setPosition(0L); AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest); // 第二次追加 appendObjectRequest.setPosition(appendObjectResult.getNextPosition()); appendObjectResult = ossClient.appendObject(appendObjectRequest); // 第三次追加 appendObjectRequest.setPosition(appendObjectResult.getNextPosition()); appendObjectResult = ossClient.appendObject(appendObjectRequest); // 關閉client ossClient.shutdown();
https://help.aliyun.com/document_detail/32013.html
import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import com.aliyun.oss.ClientException; import com.aliyun.oss.OSSClient; import com.aliyun.oss.OSSException; import com.aliyun.oss.model.AppendObjectRequest; import com.aliyun.oss.model.AppendObjectResult; import com.aliyun.oss.model.OSSObject; /** * This sample demonstrates how to upload an object by append mode * to Aliyun OSS using the OSS SDK for Java. */ public class AppendObjectSample { private static String endpoint = "*** Provide OSS endpoint ***"; private static String accessKeyId = "*** Provide your AccessKeyId ***"; private static String accessKeySecret = "*** Provide your AccessKeySecret ***"; private static String bucketName = "*** Provide bucket name ***"; private static String key = "*** Provide key ***"; public static void main(String[] args) throws IOException { /* * Constructs a client instance with your account for accessing OSS */ OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret); try { /* * Append an object from specfied input stream, keep in mind that * position should be set to zero at first time. */ String content = "Thank you for using Aliyun Object Storage Service"; InputStream instream = new ByteArrayInputStream(content.getBytes()); Long firstPosition = 0L; System.out.println("Begin to append object at position(" + firstPosition + ")"); AppendObjectResult appendObjectResult = client.appendObject( new AppendObjectRequest(bucketName, key, instream).withPosition(0L)); System.out.println("\tNext position=" + appendObjectResult.getNextPosition() + ", CRC64=" + appendObjectResult.getObjectCRC() + "\n"); /* * Continue to append the object from specfied file descriptor at last position */ Long nextPosition = appendObjectResult.getNextPosition(); System.out.println("Continue to append object at last position(" + nextPosition + "):"); appendObjectResult = client.appendObject( new AppendObjectRequest(bucketName, key, createTempFile()) .withPosition(nextPosition)); System.out.println("\tNext position=" + appendObjectResult.getNextPosition() + ", CRC64=" + appendObjectResult.getObjectCRC()); /* * View object type of the appendable object */ OSSObject object = client.getObject(bucketName, key); System.out.println("\tObject type=" + object.getObjectMetadata().getObjectType() + "\n"); // Do not forget to close object input stream if not use it any more object.getObjectContent().close(); /* * Delete the appendable object */ System.out.println("Deleting an appendable object"); client.deleteObject(bucketName, key); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message: " + oe.getErrorCode()); System.out.println("Error Code: " + oe.getErrorCode()); System.out.println("Request ID: " + oe.getRequestId()); System.out.println("Host ID: " + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message: " + ce.getMessage()); } finally { /* * Do not forget to shut down the client finally to release all allocated resources. */ client.shutdown(); } } private static File createTempFile() throws IOException { File file = File.createTempFile("oss-java-sdk-", ".txt"); file.deleteOnExit(); Writer writer = new OutputStreamWriter(new FileOutputStream(file)); writer.write("abcdefghijklmnopqrstuvwxyz\n"); writer.write("0123456789011234567890\n"); writer.close(); return file; } }
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package samples; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Writer; import com.aliyun.oss.ClientException; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; import com.aliyun.oss.model.GetObjectRequest; import com.aliyun.oss.model.OSSObject; import com.aliyun.oss.model.PutObjectRequest; /** * This sample demonstrates how to upload/download an object to/from * Aliyun OSS using the OSS SDK for Java. */ public class SimpleGetObjectSample { private static String endpoint = "*** Provide OSS endpoint ***"; private static String accessKeyId = "*** Provide your AccessKeyId ***"; private static String accessKeySecret = "*** Provide your AccessKeySecret ***"; private static String bucketName = "*** Provide bucket name ***"; private static String key = "*** Provide key ***"; public static void main(String[] args) throws IOException { /* * Constructs a client instance with your account for accessing OSS */ OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try { /** * Note that there are two ways of uploading an object to your bucket, the one * by specifying an input stream as content source, the other by specifying a file. */ /* * Upload an object to your bucket from an input stream */ System.out.println("Uploading a new object to OSS from an input stream\n"); String content = "Thank you for using Aliyun Object Storage Service"; client.putObject(bucketName, key, new ByteArrayInputStream(content.getBytes())); /* * Upload an object to your bucket from a file */ System.out.println("Uploading a new object to OSS from a file\n"); client.putObject(new PutObjectRequest(bucketName, key, createSampleFile())); /* * Download an object from your bucket */ System.out.println("Downloading an object"); OSSObject object = client.getObject(new GetObjectRequest(bucketName, key)); System.out.println("Content-Type: " + object.getObjectMetadata().getContentType()); displayTextInputStream(object.getObjectContent()); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message: " + oe.getErrorCode()); System.out.println("Error Code: " + oe.getErrorCode()); System.out.println("Request ID: " + oe.getRequestId()); System.out.println("Host ID: " + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message: " + ce.getMessage()); } finally { /* * Do not forget to shut down the client finally to release all allocated resources. */ client.shutdown(); } } private static File createSampleFile() throws IOException { File file = File.createTempFile("oss-java-sdk-", ".txt"); file.deleteOnExit(); Writer writer = new OutputStreamWriter(new FileOutputStream(file)); writer.write("abcdefghijklmnopqrstuvwxyz\n"); writer.write("0123456789011234567890\n"); writer.close(); return file; } private static void displayTextInputStream(InputStream input) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(input)); while (true) { String line = reader.readLine(); if (line == null) break; System.out.println("\t" + line); } System.out.println(); reader.close(); } }
https://github.com/aliyun/aliyun-oss-java-sdk/blob/master/src/samples/SimpleGetObjectSample.java?spm=5176.12026607.tutorial.1.9c7732e2bQ2hBA&file=SimpleGetObjectSample.java
https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.662.2cb51000luQAlv
https://segmentfault.com/a/1190000017273629?utm_source=tag-newest
在OSS控制台設置了CORS規則以后,通過JS程序去調用的時候報No ‘Access-Control-Allow-Origin’ header is present on the requested resource,可以通過下面的思路來進行下排查:
1. 確認檢查CORS規則是否設置好了,是否設置正確,正確的設置方法如下圖:
2. CORS設置都正確的話,那就檢查AllowedHeader的設置,一般建議設置為*,設置方法如下:
https://help.aliyun.com/knowledge_detail/39518.html
參數 | 是否必須 | 說明 |
---|---|---|
來源 | 是 | 指定允許的跨域請求的來源。允許多條匹配規則,多條規則需換行填寫。每條匹配規則允許使用最多一個星號(*)通配符。單獨填寫星號(*)通配符,表示允許所有來源的跨域請求。 |
允許 Methods | 是 | 指定允許的跨域請求方法。 |
允許 Headers | 否 | 指定允許的跨域請求的響應頭。大小寫不敏感,允許多條匹配規則,多條規則需換行填寫。每條匹配規則最多使用一個星號(*)通配符。建議沒有特殊需求的情況下設置為星號(*)。 |
暴露 Headers | 否 | 指定允許用戶從應用程序中訪問的響應頭(例如,一個Javascript 的 XMLHttpRequest對象)。不允許使用星號(*)通配符。 |
緩存時間 | 否 | 指定瀏覽器對特定資源的預取(OPTIONS)請求返回結果的緩存時間。 |
設置跨域訪問
跨域訪問,或者說JavaScript的跨域訪問問題,是瀏覽器出於安全考慮而設置的一個限制,即同源策略。當來自於A網站的頁面中的JavaScript代碼希望訪問B網站的時候,瀏覽器會拒絕該訪問,因為A、B兩個網站是屬於不同的域。
在實際應用中,經常會有跨域訪問的需求,比如用戶的網站www.a.com,后端使用了OSS。在網頁中提供了使用JavaScript實現的上傳功能,但是在該頁面中,只能向www.a.com發送請求,向其他網站發送的請求都會被瀏覽器拒絕。這樣就導致用戶上傳的數據必須從www.a.com中轉。如果設置了跨域訪問的話,用戶就可以直接上傳到OSS而無需從www.a.com中轉。
跨域資源共享的實現
跨域資源共享(Cross-Origin Resource Sharing),簡稱CORS,是HTML5提供的標准跨域解決方案,OSS支持CORS標准來實現跨域訪問。具體的CORS規則可以參考W3C CORS規范。其實現如下:
- CORS通過HTTP請求中附帶Origin的Header來表明自己來源域,比如上面那個例子,Origin的Header就是www.a.com。
- 服務器端接收到這個請求之后,會根據一定的規則判斷是否允許該來源域的請求。如果允許,服務器在返回的響應中會附帶上Access-Control-Allow-Origin這個Header,內容為www.a.com來表示允許該次跨域訪問。如果服務器允許所有的跨域請求,將Access-Control-Allow-Origin的Header設置為*即可。
- 瀏覽器根據是否返回了對應的Header來決定該跨域請求是否成功,如果沒有附加對應的Header,瀏覽器將會攔截該請求。如果是非簡單請求,瀏覽器會先發送一個OPTIONS請求來獲取服務器的CORS配置,如果服務器不支持接下來的操作,瀏覽器也會攔截接下來的請求。
OSS提供了CORS規則的配置,從而根據需求允許或者拒絕相應的跨域請求。該規則是配置在Bucket級別的。詳情可以參考PutBucketCORS。
細節分析
- CORS相關的Header附加等都是瀏覽器自動完成的,用戶不需要有任何額外的操作。CORS操作也只在瀏覽器環境下有意義。
- CORS請求的通過與否和OSS的身份驗證是完全獨立的,即OSS的CORS規則僅僅是用來決定是否附加CORS相關的Header的一個規則。是否攔截該請求完全由瀏覽器決定。
- 使用跨域請求的時候需要關注瀏覽器是否開啟了Cache功能。當運行在同一個瀏覽器上分別來源於www.a.com和www.b.com的兩個頁面都同時請求同一個跨域資源的時候,如果www.a.com的請求先到達服務器,服務器將資源帶上Access-Control-Allow-Origin的Header為www.a.com返回給用戶。這個時候www.b.com又發起了請求,瀏覽器會將Cache的上一次請求返回給用戶,此時Header的內容和CORS的要求不匹配,就會導致后面的請求失敗。
https://help.aliyun.com/document_detail/31870.html?spm=a2c4g.11186623.2.10.7ecc6a68CpGZAQ#concept-bwn-tjd-5db
本文介紹如何進行跨域資源共享。
跨域資源共享(Cross-origin resource sharing,簡稱CORS)允許Web端的應用程序訪問不屬於本域的資源。OSS提供跨域資源共享接口,方便您控制跨域訪問的權限。
更多關於跨域資源共享的介紹,請參見開發指南中的設置跨域訪問和API參考中PutBucketcors。
// Endpoint以杭州為例,其它Region請按實際情況填寫。 String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; // 阿里雲主賬號AccessKey擁有所有API的訪問權限,風險很高。強烈建議您創建並使用RAM賬號進行API訪問或日常運維,請登錄 https://ram.console.aliyun.com 創建RAM賬號 String accessKeyId = "<yourAccessKeyId>"; String accessKeySecret = "<yourAccessKeySecret>"; String bucketName = "<yourBucketName>"; // 創建OSSClient實例。 OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); SetBucketCORSRequest request = new SetBucketCORSRequest(bucketName); // 跨域資源共享規則的容器,每個存儲空間最多允許10條規則。 ArrayList<CORSRule> putCorsRules = new ArrayList<CORSRule>(); CORSRule corRule = new CORSRule(); ArrayList<String> allowedOrigin = new ArrayList<String>(); // 指定允許跨域請求的來源。 allowedOrigin.add( "http://www.b.com"); ArrayList<String> allowedMethod = new ArrayList<String>(); // 指定允許的跨域請求方法(GET/PUT/DELETE/POST/HEAD)。 allowedMethod.add("GET"); ArrayList<String> allowedHeader = new ArrayList<String>(); // 是否允許預取指令(OPTIONS)中Access-Control-Request-Headers頭中指定的Header。 allowedHeader.add("x-oss-test"); ArrayList<String> exposedHeader = new ArrayList<String>(); // 指定允許用戶從應用程序中訪問的響應頭。 exposedHeader.add("x-oss-test1"); // AllowedOrigins和AllowedMethods最多支持一個星號(*)通配符。星號(*)表示允許所有的域來源或者操作。 corRule.setAllowedMethods(allowedMethod); corRule.setAllowedOrigins(allowedOrigin); // AllowedHeaders和ExposeHeaders不支持通配符。 corRule.setAllowedHeaders(allowedHeader); corRule.setExposeHeaders(exposedHeader); // 指定瀏覽器對特定資源的預取(OPTIONS)請求返回結果的緩存時間,單位為秒。 corRule.setMaxAgeSeconds(10); // 最多允許10條規則。 putCorsRules.add(corRule); // 已存在的規則將被覆蓋。 request.setCorsRules(putCorsRules); ossClient.setBucketCORS(request); // 關閉OSSClient。 ossClient.shutdown();
https://help.aliyun.com/document_detail/32018.html?spm=a2c4g.11186623.6.690.676f2eaaWRN8fZ
獲取跨域資源共享規則
以下代碼用於獲取跨域資源共享規則:
// Endpoint以杭州為例,其它Region請按實際情況填寫。 String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; // 阿里雲主賬號AccessKey擁有所有API的訪問權限,風險很高。強烈建議您創建並使用RAM賬號進行API訪問或日常運維,請登錄 https://ram.console.aliyun.com 創建RAM賬號。 String accessKeyId = "<yourAccessKeyId>"; String accessKeySecret = "<yourAccessKeySecret>"; String bucketName = "<yourBucketName>"; // 創建OSSClient實例。 OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret); ArrayList<CORSRule> corsRules; // 獲取跨域資源共享規則列表。 corsRules = (ArrayList<CORSRule>) ossClient.getBucketCORSRules(bucketName); for (CORSRule rule : corsRules) { for (String allowedOrigin1 : rule.getAllowedOrigins()) { // 獲取允許的跨域請求源。 System.out.println(allowedOrigin1); } for (String allowedMethod1 : rule.getAllowedMethods()) { // 獲取允許的跨域請求方法。 System.out.println(allowedMethod1); } if (rule.getAllowedHeaders().size() > 0){ for (String allowedHeader1 : rule.getAllowedHeaders()) { // 獲取允許的頭部列表。 System.out.println(allowedHeader1); } } if (rule.getExposeHeaders().size() > 0) { for (String exposeHeader : rule.getExposeHeaders()) { // 獲取允許的頭部。 System.out.println(exposeHeader); } } if ( null != rule.getMaxAgeSeconds()) { System.out.println(rule.getMaxAgeSeconds()); } } // 關閉OSSClient。 ossClient.shutdown();
https://help.aliyun.com/document_detail/32018.html?spm=a2c4g.11186623.6.690.676f2eaaWRN8fZ
簽名錯誤 (signature not match)
簽名錯誤建議您排查以下問題:
-
參考在Header中包含簽名中的簽名方法以及示例,切記其中的\n是不能少的。
-
URL中出現特殊字符“+”等時,會有瀏覽器無法識別的情況,需要對簽名做url coding,對“+”等做url編碼,將+轉換為“%2b”,瀏覽器才能識別。
-
使用如下的簽名驗證工具自行查看簽名的過程,請您參考:https://bbs.aliyun.com/read/233851.html
推薦直接使用我們提供的SDK,這樣避免您自己進行簽名,我們幫您直接實現了簽名的過程,請您參考:這里。
https://help.aliyun.com/knowledge_detail/66098.html?spm=a2c4g.11186631.2.8.6e892a8dwb2Hk5
java實現生成url簽名的代碼示例
生成簽名以后的URL的示例代碼如下:
// Generate a presigned URL Date expires = new Date (new Date().getTime() + 1000 * 60); // 1 minute to expire GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key); generatePresignedUrlRequest.setExpiration(expires); URL url = client.generatePresignedUrl(generatePresignedUrlRequest); System.out.println(url.toString());
這段代碼假定指定bucketName和key的Object已經上傳到OSS,用戶可以根據修改設定expires,即過期時間。更詳細的操作可以參考OSSClient#generatePresignedUrl方法和GeneratePresignedUrlRequest類的幫助。
詳細Java SDK文檔可以參考:點擊查看
https://help.aliyun.com/knowledge_list/51639.html?spm=a2c4g.11186623.3.3.697c7681h465JK
@Slf4j @Service public class AliOSSServiceImpl implements OSSService { @Autowired private OssConfig ossConfig; @Override public UploadOSSVO generatePresignedUrl(UploadOSSReq req) { String bucketName = ossConfig.getBucket(); OSSClient ossClient = null; try { ossClient = getOssClient(); // 設置文件路徑和名稱 // https://filetest.gongbangbang.com/resources/u/2019/02/11/ea05ef6c4fce4e04a910fb38a2643a1fBJxmpf.jpg String key = getObjectName(req); // 創建請求。 GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key); // HttpMethod為PUT。 generatePresignedUrlRequest.setMethod(HttpMethod.PUT);//要使用put方法進行上傳 // // 添加用戶自定義元信息。 generatePresignedUrlRequest.addUserMetadata("author", "jackie"); // 添加Content-Type。 generatePresignedUrlRequest.setContentType("application/octet-stream");//要指定HttpHeader // 設置URL過期時間為1小時。 generatePresignedUrlRequest.setExpiration(LocalDateTime.now().plusHours(1).toDate()); // 上傳文件 URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest); String query = url.getQuery(); return new UploadOSSVO(ossConfig.getOssResourceUrl(key) + "?" + query); } catch (OSSException oe) { log.error("生成url失敗 OSSException {}", oe.getMessage(), oe); throw oe; } catch (ClientException ce) { log.error("生成url失敗 ClientException {}", ce.getErrorMessage()); throw ce; } finally { if (ossClient != null) { ossClient.shutdown(); } } } /** * 上傳文件。 * * @param file 需要上傳的文件路徑 * @return 如果上傳的文件是圖片的話,會返回圖片的"URL",如果非圖片的話會返回"非圖片,不可預覽。文件路徑為:+文件路徑" */ @Override public String upLoad(File file) throws IOException { log.info("------OSS文件上傳開始--------{}", file.getName()); Assert.notNull(file, "往ali oss 上傳的文件為空"); Assert.isTrue(file.exists(), "往ali oss上傳的文件不存在"); String bucketName = ossConfig.getBucket(); OSSClient ossClient = null; try { ossClient = getOssClient(); // 設置文件路徑和名稱 // https://filetest.gongbangbang.com/resources/u/2019/02/11/ea05ef6c4fce4e04a910fb38a2643a1fBJxmpf.jpg String key = getObjectName(new UploadOSSReq(FilenameUtils.getExtension(file.getName()))); // 上傳文件 PutObjectResult putObjectResult = ossClient.putObject(bucketName, key, file); String ossResourceUrl = ossConfig.getOssResourceUrl(key); if (putObjectResult != null) { log.info("PutObjectResult:{}", JSON.toJSONString(putObjectResult)); // 設置權限(公開讀) ossClient.setObjectAcl(bucketName, key, CannedAccessControlList.PublicRead); log.info("------OSS文件上傳成功------ {}", ossResourceUrl); FileUtils.deleteQuietly(file); return ossResourceUrl; } log.warn("OSS文件上傳失敗。 putObjectResult is null"); throw new IOException("OSS文件上傳失敗。putObjectResult is null"); } catch (OSSException oe) { log.error(oe.getMessage(), oe); throw oe; } catch (ClientException ce) { log.error(ce.getErrorMessage(), ce); throw ce; } finally { if (ossClient != null) { ossClient.shutdown(); } } } /** * 上傳的資源在OSS上的路徑 * * @param req * @return */ private String getObjectName(UploadOSSReq req) { return ossConfig.getPath() + LocalDate.now().toString("yyyy/MM/dd") + "/" + RandomUtils.getRandomFileName() + req.getSuffix(); } /** * 初始化OSS Client對象 * * @return */ private OSSClient getOssClient() { OSSClient ossClient = new OSSClient(ossConfig.getEndpoint(), ossConfig.getAccessId(), ossConfig.getAccessKey()); // 判斷容器是否存在,不存在就創建 String bucketName = ossConfig.getBucket(); if (!ossClient.doesBucketExist(bucketName)) { ossClient.createBucket(bucketName); CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); ossClient.createBucket(createBucketRequest); } return ossClient; } }