阿里雲對象存儲服務(Object Storage Service,簡稱 OSS),是阿里雲提供的海量、安全、低成本、高可靠的雲存儲服務。其數據設計持久性不低於 99.9999999999%(12 個 9),服務設計可用性(或業務連續性)不低於 99.995%。
OSS 具備與平臺無關的 RESTful API 接口,您能夠在任何應用、任什麼時候間、任何地點存儲和訪問任意類型的數據。
您可使用阿里雲提供的 API、SDK 接口或者 OSS 遷移工具輕鬆地將海量數據移入或移出阿里雲 OSS。數據存儲到阿里雲 OSS 之後,您能夠選擇標準存儲(Standard)做爲移動應用、大型網站、圖片分享或熱點音視頻的主要存儲方式,也能夠選擇成本更低、存儲期限更長的低頻訪問存儲(Infrequent Access)和歸檔存儲(Archive)做爲不常常訪問數據的存儲方式。html以上內容引用自阿里雲官網前端
目前阿里雲OSS的價格是40GB/年9元,若是你是白嫖用戶,那麼請轉向七牛。java
你覺得購買了40G/年的容量就不用付費了嗎?那你就錯了,這只是存儲費用,使用OSS還須要支付流量費用。可是流量費用是單獨計算的。web
它能夠搭建本身的牀圖(配合PicGO),備份網站,數據庫(配合寶塔)等。也能夠在開發過程當中充當文件服務器,阿里雲OSS宣稱99.9999999999%的可靠性,另外加上價格相對低廉,是做爲圖片/文件服務器的不二之選。spring
存儲空間是用戶用於存儲對象(Object)的容器,全部的對象都必須隸屬於某個存儲空間。存儲空間具備各類配置屬性,包括地域、訪問權限、存儲類型等。用戶能夠根據實際需求,建立不一樣類型的存儲空間來存儲不一樣的數據。數據庫
存儲空間的命名規範以下:apache
只能包括小寫字母、數字和短橫線(-)。數組
必須以小寫字母或者數字開頭和結尾。安全
長度必須在 3–63 字節之間。springboot
對象是 OSS 存儲數據的基本單元,也被稱爲 OSS 的文件。對象由元信息(Object Meta),用戶數據(Data)和文件名(Key)組成。對象由存儲空間內部惟一的 Key 來標識。對象元信息是一組鍵值對,表示了對象的一些屬性,好比最後修改時間、大小等信息,同時用戶也能夠在元信息中存儲一些自定義的信息。
對象的生命週期是從上傳成功到被刪除爲止。在整個生命週期內,只有經過追加上傳的 Object 能夠繼續經過追加上傳寫入數據,其餘上傳方式上傳的 Object 內容沒法編輯,您能夠經過重複上傳同名的對象來覆蓋以前的對象。
對象的命名規範以下:
使用 UTF-8 編碼。
長度必須在 1–1023 字節之間。
不能以正斜線(/)或者反斜線(\)開頭。
Endpoint 表示 OSS 對外服務的訪問域名。OSS 以 HTTP RESTful API 的形式對外提供服務,當訪問不一樣的 Region 的時候,須要不一樣的域名。經過內網和外網訪問同一個 Region 所須要的 Endpoint 也是不一樣的。例如杭州 Region 的外網 Endpoint 是 oss-cn-hangzhou.aliyuncs.com,內網 Endpoint 是 oss-cn-hangzhou-internal.aliyuncs.com。
AccessKey(簡稱 AK)指的是訪問身份驗證中用到的 AccessKeyId 和 AccessKeySecret。OSS 經過使用 AccessKeyId 和 AccessKeySecret 對稱加密的方法來驗證某個請求的發送者身份。AccessKeyId 用於標識用戶;AccessKeySecret 是用戶用於加密簽名字符串和 OSS 用來驗證簽名字符串的密鑰,必須保密。對於 OSS 來講,AccessKey 的來源有:
這裏介紹一份基於java實現的阿里雲OSS工具類,代碼基於阿里雲官方OSS官方API文檔。此項目使用Maven搭建,須要使用幾個依賴。具體依賴以下:
<?xml version="1.0" encoding="UTF-8"?> <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> <groupId>cn.rayfoo</groupId> <artifactId>ALiOSS-demo</artifactId> <version>1.0-SNAPSHOT</version> <properties> <!-- maven-compiler-plugin 將會使用指定的 JDK 版本將 java 文件編譯爲 class 文件(針對編譯運行環境) --> <maven.compiler.target>1.8</maven.compiler.target> <!-- maven-compiler-plugin 將會使用指定的 JDK 版本對源代碼進行編譯(針對編譯運行環境) --> <maven.compiler.source>1.8</maven.compiler.source> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.8.0</version> </dependency> </dependencies> </project>
此工具類須要調用resource下的aliyunOSS.properties文件,具體配置以下
AccessKey=yourAccessKey AccessKeySecret=yourAccessKeySecret Buckets=yourBuckets EndPoint=https://oss-cn-beijing.aliyuncs.com
因爲此工具類又用到我封裝的另外一個工具類:PropertiesReader,因此在此處提供該工具類的代碼。
注意:
package cn.rayfoo.util; import java.io.InputStream; import java.util.Properties; /** * Created by rayfoo@qq.com Luna on 2020/4/15 18:38 * Description : 讀取配置文件工具類 */ public class PropertiesReader { //建立Properties對象 private static Properties property = new Properties(); //在靜態塊中加載資源 static { //使用try(){}.. 獲取數據源 //注意 * 這是jdk1.7開始支持的特性,若是使用的是低版本 須要提高jdk版本 或者更改寫法 try ( InputStream in = PropertiesReader.class.getResourceAsStream("/aliyunOSS.properties"); ) { property.load(in); } catch (Exception e) { e.printStackTrace(); } } /** * 返回Properties對象 * @return */ public static Properties getProperties(){ return property; } /** * 獲取字符串類型的值 * @param key * @return */ public static String get(String key) { return property.getProperty(key); } /** * 獲取Integer類型的值 * @param key * @return */ public static Integer getInteger(String key) { String value = get(key); return null == value ? null : Integer.valueOf(value); } /** * 獲取Boolean類型的值 * @param key * @return */ public static Boolean getBoolean(String key) { String value = get(key); return null == value ? null : Boolean.valueOf(value); } /** * 設置一個鍵值對 * @param key * @param value */ public static void set(String key,String value){ property.setProperty(key,value); } /** * 添加一個鍵值對 * @param key * @param value */ public static void add(String key,Object value){ property.put(key,value); } }
該工具類集成了OSS的上傳、下載等功能。
下面的代碼中會用到不少個參數名,咱們要先明白它們表明什麼
參數名 | 含義 |
---|---|
oranName | 表明用戶傳過來未經處理的文件名 例如/img/a.jpg |
objectName | 表明去掉前面/ 加上uuid後的文件名 如img/330ddd7feb6d456f8ee97092d7675c90a.jgp |
realName | 指的是存放在OSS中的全路徑 |
屬性名 | 介紹 |
---|---|
accessKeyId | 這個屬性會從aliyunOSS.properties中讀取key爲AccessKey的內容 |
accessKeySecret | 這個屬性會從aliyunOSS.properties中讀取key爲AccessKeySecret的內容 |
endpoint | 這個屬性會從aliyunOSS.properties中讀取key爲Endpoint的內容 |
bucketName | 這個屬性會從aliyunOSS.properties中讀取key爲BucketName的內容 |
方法名 | 介紹 |
---|---|
getURLHead() | 返回url頭信息,即https://+bucketName+endpoint |
String getObjectName(String fileURL) | 經過文件URL反向解析文件名 |
List
|
批量獲取 objectName |
String getRealName(String oranName) | 獲取存放在OSS中的全路徑 |
void printUploadSuccessInfo(String fileURL) | 上傳成功後打印文件的存儲地址,測試方法 |
void printDeleteSuccessInfo(String fileURL) | 刪除成功後打印文件的存儲地址,測試方法 |
String getRandomImageName(String oranName) | 在oranName以前加入一個uuid並返回新的oranName |
String createBucket(String bucket) | 建立一個新的Bucket |
String getBucketName(String fileURL) | 根據url獲取bucketName |
void useBucketName(String bucket) | 切換到某個bucket |
void useBucketNameByURL(String fileURL) | 切換到url所在的bucket |
String upLoadTextFile(String oranFileName, String content) | 上傳一個文本文件到服務器上,獲取realName |
String uploadBytesFile(String oranFileName, byte[] content) | 上傳一個byte數組到服務器上,可用於web中的圖片提交,獲取realName |
String uploadNetworkFlows(String oranFileName, String url) | 上傳網絡流,獲取realName |
String uploadFileInputSteam(String oranFileName, File file) | 上傳文件流,獲取realName |
String uploadLocalFile(String oranFileName, String localFileName) | 上傳一個本地文件,獲取realName |
void deleteFile(String fileURL) | 刪除指定路徑下的一個文件 |
void deleteFile(List
|
刪除指定路徑下的多個文件 |
boolean exists(String fileURL) | 存在爲true,不存在爲false |
void downloadFileToLoacal(String fileURL, String localFileName) | 從OSS中下載一個文件到本地 |
StringBuffer downloadStream(String fileURL) | 以流的方式讀取一個文件 並打印 返回讀取到的內容 |
Object getCloudPropertiesGetValue(String fileName, String key) | 以流的方式讀取一個雲端properties文件的key對應的value 並打印 |
package cn.rayfoo.util; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.model.*; import java.io.*; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.UUID; /** * Created by rayfoo@qq.com Luna on 2020/4/15 23:12 * Description:阿里雲 OSS 文件上傳工具類 * oranName : 表明用戶傳過來未經處理的文件名 例如/img/a.jpg * objectName : 表明去掉前面/ 加上uuid後的文件名 如img/330ddd7feb6d456f8ee97092d7675c90a.jgp * getRealName(objectName) : 指的是存放在OSS中的全路徑 */ public class AliOSSUtil { //AccessKey private static String accessKeyId = null; //AccessKeySecret private static String accessKeySecret = null; //Endpoint private static String endpoint = null; //bucketName private static String bucketName = null; /** * 靜態塊 */ static { //初始化AccessKey accessKeyId = PropertiesReader.get("AccessKey"); //初始化AccessKeySecret accessKeySecret = PropertiesReader.get("AccessKeySecret"); //初始化Endpoint endpoint = PropertiesReader.get("EndPoint"); //初始化bucketName bucketName = PropertiesReader.get("Buckets"); } /** * 私有化構造 */ private AliOSSUtil() { } /** * 獲取圖片的URL頭信息 * * @return 返回url頭信息 */ private static String getURLHead() { //從哪一個位置截取 int cutPoint = endpoint.lastIndexOf('/') + 1; //http頭 String head = endpoint.substring(0, cutPoint); //服務器地址信息 String tail = endpoint.substring(cutPoint); //返回結果 return head + bucketName + "." + tail + "/"; } /** * 經過文件URL反向解析文件名 * * @param fileURL 文件URL * @return 原文件名 */ private static String getObjectName(String fileURL) { return fileURL.substring(getURLHead().length()); } /** * 批量獲取 objectName * * @param fileURLs url列表 * @return objectName列表 */ private static List<String> getObjectNames(List<String> fileURLs) { //建立返回對象 List<String> result = null; //迭代轉換 for (String item : fileURLs) { result.add(item.substring(getURLHead().length())); } return result; } /** * 獲取存儲在服務器上的地址 * * @param oranName 文件名 * @return 文件URL */ private static String getRealName(String oranName) { return getURLHead() + oranName; } /** * 打印文件的存儲地址 * * @param fileURL 文件URL */ private static void printUploadSuccessInfo(String fileURL) { //上傳成功 System.out.println("upload success, path = " + getRealName(fileURL)); } /** * 打印文件的存儲地址 * * @param fileURL 文件URL */ private static void printDeleteSuccessInfo(String fileURL) { //上傳成功 System.out.println("delete success, path = " + getRealName(fileURL)); } /** * 獲取一個隨機的文件名 * * @param oranName 初始的文件名 * @return 返回加uuid後的文件名 */ private static String getRandomImageName(String oranName) { //獲取一個uuid 去掉- String uuid = UUID.randomUUID().toString().replace("-", ""); //查一下是否帶路徑 int cutPoint = oranName.lastIndexOf("/") + 1; //若是存在路徑 if (cutPoint != 0) { //掐頭 若是開頭是/ 則去掉 String head = oranName.indexOf("/") == 0 ? oranName.substring(1, cutPoint) : oranName.substring(0, cutPoint); //去尾 String tail = oranName.substring(cutPoint); //返回正確的帶路徑的圖片名稱 return head + uuid + tail; } //不存在 直接返回 return uuid + oranName; } /** * 建立一個Bucket,這個參數由參數傳入 並不是配置文件讀取 * * @param bucket BucketName 此處參數名喂Bucket是爲了避免和buckName衝突 */ public static String createBucket(String bucket) { // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 建立存儲空間。 ossClient.createBucket(bucket); // 關閉OSSClient。 ossClient.shutdown(); return bucket; } /** * 根據url獲取bucketName * * @param fileURL 文件的URL * @return bucketName */ public static String getBucketName(String fileURL) { //前綴 String prefix = "http://"; //後綴 String suffix = "."; //截取起始位置 int beginIndex = fileURL.indexOf(prefix); //截取結束位置 int endIndex = fileURL.indexOf(suffix); //若是不是http if (beginIndex == -1) { prefix = "https://"; beginIndex = fileURL.indexOf(prefix); //若是仍是-1 那就是沒找到 返回-1便可 if (beginIndex == -1) return null; } //設置起始位置 beginIndex = prefix.length(); //返回bucketName return fileURL.substring(beginIndex, endIndex); } /** * 切換bucket * * @param bucket 新的bucket名稱 */ public static void useBucketName(String bucket) { bucketName = bucket; PropertiesReader.set("Buckets", bucket); } /** * 切換bucket * * @param fileURL 根據URL設置新的BucketName */ public static void useBucketNameByURL(String fileURL) { PropertiesReader.set("Buckets", getBucketName(fileURL)); } /** * 上傳一個文本文件到服務器上 * * @param oranFileName 上傳到服務器上的文件路徑和名稱 文本文件通常以.txt爲後綴 * @param content 上傳的內容 */ public static String upLoadTextFile(String oranFileName, String content) { // <yourObjectName>上傳文件到OSS時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg String objectName = getRandomImageName(oranFileName); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 上傳內容到指定的存儲空間(bucketName)並保存爲指定的文件名稱(objectName)。 ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes())); //上傳成功 打印文件存儲地址 printUploadSuccessInfo(objectName); // 關閉OSSClient。 ossClient.shutdown(); //返回文件在服務器上的全路徑+名稱 return getRealName(objectName); } /** * 上傳一個byte數組到服務器上 * * @param oranFileName 上傳到服務器上的文件路徑和名稱 * @param content 上傳的內容 */ public static String uploadBytesFile(String oranFileName, byte[] content) { // <yourObjectName>上傳文件到OSS時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg String objectName = getRandomImageName(oranFileName); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 上傳Byte數組。 ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content)); //上傳成功 打印文件存儲地址 printUploadSuccessInfo(objectName); // 關閉OSSClient。 ossClient.shutdown(); //返回文件在服務器上的全路徑+名稱 return getRealName(objectName); } /** * 上傳網絡流 * * @param oranFileName 上傳到服務器上的文件路徑和名稱 * @param url 網絡上文件的url */ public static String uploadNetworkFlows(String oranFileName, String url) { // <yourObjectName>上傳文件到OSS時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg String objectName = getRandomImageName(oranFileName); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try ( // 上傳網絡流。 InputStream inputStream = new URL(url).openStream();) { //上傳到OSS ossClient.putObject(bucketName, objectName, inputStream); } catch (Exception e) { e.printStackTrace(); } //上傳成功 打印文件存儲地址 printUploadSuccessInfo(objectName); // 關閉OSSClient。 ossClient.shutdown(); //返回文件在服務器上的全路徑+名稱 return getRealName(objectName); } /** * 上傳文件流 * * @param oranFileName 上傳到服務器上的文件路徑和名稱 * @param file 來自本地的文件或者文件流 */ public static String uploadFileInputSteam(String oranFileName, File file) { // <yourObjectName>上傳文件到OSS時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg String objectName = getRandomImageName(oranFileName); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 上傳文件流。 try (InputStream inputStream = new FileInputStream(file);) { //上傳到OSS ossClient.putObject(bucketName, objectName, inputStream); } catch (Exception ex) { ex.printStackTrace(); } //上傳成功 打印文件存儲地址 printUploadSuccessInfo(objectName); // 關閉OSSClient。 ossClient.shutdown(); //返回文件在服務器上的全路徑+名稱 return getRealName(objectName); } /** * 上傳一個本地文件 * * @param oranFileName 上傳到服務器上的名稱和路徑 * @param localFileName 須要提供路徑和文件名 */ public static String uploadLocalFile(String oranFileName, String localFileName) { // <yourObjectName>上傳文件到OSS時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg String objectName = getRandomImageName(oranFileName); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 建立PutObjectRequest對象。 PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(localFileName)); // 若是須要上傳時設置存儲類型與訪問權限,請參考如下示例代碼。 // ObjectMetadata metadata = new ObjectMetadata(); // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); // metadata.setObjectAcl(CannedAccessControlList.Private); // putObjectRequest.setMetadata(metadata); // 上傳文件。 ossClient.putObject(putObjectRequest); //上傳成功 打印文件存儲地址 printUploadSuccessInfo(objectName); // 關閉OSSClient。 ossClient.shutdown(); //返回文件在服務器上的全路徑+名稱 return getRealName(objectName); } /** * 刪除指定路徑下的一個文件 * * @param fileURL 文件的全稱 */ public static void deleteFile(String fileURL) { // 反向解析文件名 String objectName = getObjectName(fileURL); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 刪除文件。如需刪除文件夾,請將ObjectName設置爲對應的文件夾名稱。若是文件夾非空,則須要將文件夾下的全部object刪除後才能刪除該文件夾。 ossClient.deleteObject(bucketName, objectName); //刪除成功 打印文件存儲地址 printDeleteSuccessInfo(fileURL); // 關閉OSSClient。 ossClient.shutdown(); } /** * 刪除指定路徑下的多個文件--該方法未測試 * * @param fileURL 要刪除的多個文件的集合 */ public static void deleteFile(List<String> fileURL) { // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 刪除文件。key等同於ObjectName,表示刪除OSS文件時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg。 List<String> keys = new ArrayList<>(); //批量添加要刪除的元素 for (String item : fileURL) { keys.add(getObjectName(item)); } //刪除 DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys)); List<String> deletedObjects = deleteObjectsResult.getDeletedObjects(); //批量添加要刪除的元素 for (String item : fileURL) { printDeleteSuccessInfo(item); } // 關閉OSSClient。 ossClient.shutdown(); } /** * 經過文件的URL 判斷文件是否存在 * * @param fileURL 文件的URL * @return 文件是否存在 */ public static boolean exists(String fileURL) { // 反向解析文件名 String objectName = getObjectName(fileURL); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 判斷文件是否存在。doesObjectExist還有一個參數isOnlyInOSS,若是爲true則忽略302重定向或鏡像;若是爲false,則考慮302重定向或鏡像。 boolean found = ossClient.doesObjectExist(bucketName, objectName); // 關閉OSSClient。 ossClient.shutdown(); // 返回是否存在 return found; } /** * 從OSS中下載一個文件 * * @param fileURL 文件的url * @param localFileName 下載到本地的文件名稱 */ public static void downloadFileToLoacal(String fileURL, String localFileName) { //將url解析成objectName String objectName = getObjectName(fileURL); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 下載OSS文件到本地文件。若是指定的本地文件存在會覆蓋,不存在則新建。 ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(localFileName)); // 關閉OSSClient。 ossClient.shutdown(); } /** * 以流的方式讀取一個文件 並打印 * * @param fileURL 文件的url */ public static StringBuffer downloadStream(String fileURL) { //<yourObjectName>表示從OSS下載文件時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg。 String objectName = getObjectName(fileURL); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // ossObject包含文件所在的存儲空間名稱、文件名稱、文件元信息以及一個輸入流。 OSSObject ossObject = ossClient.getObject(bucketName, objectName); // 讀取文件內容。 System.out.println("Object content:"); StringBuffer sb = new StringBuffer(); //使用try(){}..關閉資源 try (BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));) { //讀取 while (true) { String line = reader.readLine(); if (line == null) break; sb.append(line); System.out.println("\n" + line); } } catch (Exception ex) { ex.printStackTrace(); } // 關閉OSSClient。 ossClient.shutdown(); //返回讀取到的內容 return sb; } /** * 以流的方式讀取一個雲端properties文件的key對應的value 並打印 * * @param fileName 文件的url */ public static Object getCloudPropertiesGetValue(String fileName, String key) { //properties 文件夾的前綴 String prefix = "properties/"; //properties 文件夾的後綴 String suffix = ".properties"; //<yourObjectName>表示從OSS下載文件時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg。 String objectName = prefix + fileName + suffix; // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // ossObject包含文件所在的存儲空間名稱、文件名稱、文件元信息以及一個輸入流。 OSSObject ossObject = ossClient.getObject(bucketName, objectName); // 讀取文件內容。 System.out.println("Object content:"); //獲取一個Properties對象 Properties properties = PropertiesReader.getProperties(); try ( //獲取文件流 InputStream inputStream = ossObject.getObjectContent();) { properties.load(inputStream); } catch (Exception ex) { ex.printStackTrace(); } // 關閉OSSClient。 ossClient.shutdown(); //返回讀取到的內容 return properties.get(key); } }
Properties文件
aliyun.AccessKeyID=yourAccessKeyID aliyun.AccessKeySecret=yourAccessKeySecret aliyun.Buckets=yourBuckets aliyun.EndPoint=https://oss-cn-beijing.aliyuncs.com aliyun.prefix=prefix/
工具類代碼
package cn.rayfoo.utils; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.UUID; /** * @Author: rayfoo@qq.com * @Date: 2020/7/13 3:11 下午 * @Description: */ public class AliyunOSSUtils { /** * 阿里雲的配置參數 */ private static String accessKeyId = null; private static String accessKeySecret = null; private static String endpoint = null; private static String bucketName = null; /** * 存儲在OSS中的前綴名 */ private static String file_prefix = null; /** * 靜態塊 */ static { //初始化AccessKey accessKeyId = PropertiesReader.get("aliyun.AccessKeyID"); //初始化AccessKeySecret accessKeySecret = PropertiesReader.get("aliyun.AccessKeySecret"); //初始化Endpoint endpoint = PropertiesReader.get("aliyun.EndPoint"); //初始化bucketName bucketName = PropertiesReader.get("aliyun.Buckets"); //初始化前綴 file_prefix = PropertiesReader.get("aliyun.prefix"); } /** * 私有化構造 */ private AliyunOSSUtils() { } /** * 獲取圖片的URL頭信息 * * @return 返回url頭信息 */ private static String getURLHead() { //從哪一個位置截取 int cutPoint = endpoint.lastIndexOf('/') + 1; //http頭 String head = endpoint.substring(0, cutPoint); //服務器地址信息 String tail = endpoint.substring(cutPoint); //返回結果 return head + bucketName + "." + tail + "/"; } /** * 獲取存儲在服務器上的地址 * * @param oranName 文件名 * @return 文件URL */ private static String getRealName(String oranName) { return getURLHead() + oranName; } /** * 獲取一個隨機的文件名 * * @param oranName 初始的文件名 * @return 返回加uuid後的文件名 */ private static String getRandomImageName(String oranName) { //獲取一個uuid 去掉- String uuid = UUID.randomUUID().toString().replace("-", ""); //查一下是否帶路徑 int cutPoint = oranName.lastIndexOf("/") + 1; //若是存在路徑 if (cutPoint != 0) { //掐頭 若是開頭是/ 則去掉 String head = oranName.indexOf("/") == 0 ? oranName.substring(1, cutPoint) : oranName.substring(0, cutPoint); //去尾 String tail = oranName.substring(cutPoint); //返回正確的帶路徑的圖片名稱 return file_prefix + head + uuid + tail; } //不存在 直接返回 return file_prefix + uuid + oranName; } /** * MultipartFile2File * @param multipartFile * @return */ private static File transferToFile(MultipartFile multipartFile) { //選擇用緩衝區來實現這個轉換即便用java 建立的臨時文件 使用 MultipartFile.transferto()方法 。 File file = null; try { //獲取文件名 String originalFilename = multipartFile.getOriginalFilename(); //獲取最後一個"."的位置 int cutPoint = originalFilename.lastIndexOf("."); //獲取文件名 String prefix = originalFilename.substring(0,cutPoint); //獲取後綴名 String suffix = originalFilename.substring(cutPoint + 1); //建立臨時文件 file = File.createTempFile(prefix, suffix); //multipartFile2file multipartFile.transferTo(file); //刪除臨時文件 file.deleteOnExit(); } catch (IOException e) { e.printStackTrace(); } return file; } /** * 上傳文件流 * * @param oranFileName 上傳到服務器上的文件路徑和名稱 * @param file 來自本地的文件或者文件流 */ public static String uploadFileInputSteam(String oranFileName, MultipartFile file) { // <yourObjectName>上傳文件到OSS時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg String objectName = getRandomImageName(oranFileName); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 上傳文件流 try (InputStream inputStream = new FileInputStream(transferToFile(file))) { //上傳到OSS ossClient.putObject(bucketName, objectName, inputStream); } catch (Exception ex) { ex.printStackTrace(); } // 關閉OSSClient。 ossClient.shutdown(); //返回文件在服務器上的全路徑+名稱 return getRealName(objectName); } /** * 上傳文件流 * * @param oranFileName 上傳到服務器上的文件路徑和名稱 * @param file 來自本地的文件或者文件流 */ public static String uploadFileInputSteam(String oranFileName, File file) { // <yourObjectName>上傳文件到OSS時須要指定包含文件後綴在內的完整路徑,例如abc/efg/123.jpg String objectName = getRandomImageName(oranFileName); // 建立OSSClient實例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); // 上傳文件流。 try (InputStream inputStream = new FileInputStream(file);) { //上傳到OSS ossClient.putObject(bucketName, objectName, inputStream); } catch (Exception ex) { ex.printStackTrace(); } // 關閉OSSClient。 ossClient.shutdown(); //返回文件在服務器上的全路徑+名稱 return getRealName(objectName); } }
前端代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>文件上傳</title> </head> <body> <h1>文件上傳Demo</h1> <hr> <form id="myform" action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="file"> <input type="submit" value="提交"> </form> </body> </html>
後臺代碼
package cn.rayfoo.controller; import cn.rayfoo.utils.AliyunOSSUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; /** * @Author: rayfoo@qq.com * @Date: 2020/7/13 3:15 下午 * @Description: */ @RestController public class FileController { @PostMapping("/upload") public String upload(@RequestParam("file")MultipartFile file, HttpServletRequest request){ //若是文件爲空 返回錯誤信息 if(file.isEmpty()){ return "field"; } //獲取原文件名 String originalFilename = file.getOriginalFilename(); //返回圖片的url return AliyunOSSUtils.uploadFileInputSteam(originalFilename,file); } }