SpringBoot整合阿里雲OSS


阿里雲OSS Java工具類

阿里雲對象存儲服務(Object Storage Service,簡稱 OSS),是阿里雲提供的海量、安全、低成本、高可靠的雲存儲服務。其數據設計持久性不低於 99.9999999999%(12 個 9),服務設計可用性(或業務連續性)不低於 99.995%。
OSS 具有與平台無關的 RESTful API 接口,您可以在任何應用、任何時間、任何地點存儲和訪問任意類型的數據。
您可以使用阿里雲提供的 API、SDK 接口或者 OSS 遷移工具輕松地將海量數據移入或移出阿里雲 OSS。數據存儲到阿里雲 OSS 以后,您可以選擇標准存儲(Standard)作為移動應用、大型網站、圖片分享或熱點音視頻的主要存儲方式,也可以選擇成本更低、存儲期限更長的低頻訪問存儲(Infrequent Access)和歸檔存儲(Archive)作為不經常訪問數據的存儲方式。

以上內容引用自阿里雲官網

價格

目前阿里雲OSS的價格是40GB/年9元,如果你是白嫖用戶,那么請轉向七牛。

你以為購買了40G/年的容量就不用付費了嗎?那你就錯了,這只是存儲費用,使用OSS還需要支付流量費用。但是流量費用是單獨計算的。

  • 存儲價格 0.148 元 /GB/月
  • 流量價格 忙時 0.50 元 /GB
  • 請求費用 0.01 元 /萬次
    上述的40G/年指的是存儲價格,並不包含流量和請求費用。
    具體內容可參見:計價表

OSS可以做什么?

它可以搭建自己的床圖(配合PicGO),備份網站,數據庫(配合寶塔)等。也可以在開發過程中充當文件服務器,阿里雲OSS宣稱99.9999999999%的可靠性,另外加上價格相對低廉,是作為圖片/文件服務器的不二之選。

你要知道的一些概念

存儲空間(Bucket)

存儲空間是用戶用於存儲對象(Object)的容器,所有的對象都必須隸屬於某個存儲空間。存儲空間具有各種配置屬性,包括地域、訪問權限、存儲類型等。用戶可以根據實際需求,創建不同類型的存儲空間來存儲不同的數據。

  • 同一個存儲空間的內部是扁平的,沒有文件系統的目錄等概念,所有的對象都直接隸屬於其對應的存儲空間。
  • 每個用戶可以擁有多個存儲空間。
  • 存儲空間的名稱在 OSS 范圍內必須是全局唯一的,一旦創建之后無法修改名稱。
  • 存儲空間內部的對象數目沒有限制。

存儲空間的命名規范如下:

  • 只能包括小寫字母、數字和短橫線(-)。

  • 必須以小寫字母或者數字開頭和結尾。

  • 長度必須在 3–63 字節之間。

對象/文件(Object)

對象是 OSS 存儲數據的基本單元,也被稱為 OSS 的文件。對象由元信息(Object Meta),用戶數據(Data)和文件名(Key)組成。對象由存儲空間內部唯一的 Key 來標識。對象元信息是一組鍵值對,表示了對象的一些屬性,比如最后修改時間、大小等信息,同時用戶也可以在元信息中存儲一些自定義的信息。

對象的生命周期是從上傳成功到被刪除為止。在整個生命周期內,只有通過追加上傳的 Object 可以繼續通過追加上傳寫入數據,其他上傳方式上傳的 Object 內容無法編輯,您可以通過重復上傳同名的對象來覆蓋之前的對象。

對象的命名規范如下:

  • 使用 UTF-8 編碼。

  • 長度必須在 1–1023 字節之間。

  • 不能以正斜線(/)或者反斜線(\)開頭。

Endpoint(訪問域名)

Endpoint 表示 OSS 對外服務的訪問域名。OSS 以 HTTP RESTful API 的形式對外提供服務,當訪問不同的 Region 的時候,需要不同的域名。通過內網和外網訪問同一個 Region 所需要的 Endpoint 也是不同的。例如杭州 Region 的外網 Endpoint 是 oss-cn-hangzhou.aliyuncs.com,內網 Endpoint 是 oss-cn-hangzhou-internal.aliyuncs.com。

AccessKey(訪問密鑰)

AccessKey(簡稱 AK)指的是訪問身份驗證中用到的 AccessKeyId 和 AccessKeySecret。OSS 通過使用 AccessKeyId 和 AccessKeySecret 對稱加密的方法來驗證某個請求的發送者身份。AccessKeyId 用於標識用戶;AccessKeySecret 是用戶用於加密簽名字符串和 OSS 用來驗證簽名字符串的密鑰,必須保密。對於 OSS 來說,AccessKey 的來源有:

  • Bucket 的擁有者申請的 AccessKey。
  • 被 Bucket 的擁有者通過 RAM 授權給第三方請求者的 AccessKey。
  • 被 Bucket 的擁有者通過 STS 授權給第三方請求者的 AccessKey。

JAVA工具類-准備篇

這里介紹一份基於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,所以在此處提供該工具類的代碼。

注意:

  • 這份工具類建議需要1.8及以上版本的JDK
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 getObjectNames(List fileURLs) 批量獲取 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 fileURL) 刪除指定路徑下的多個文件
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);
    }
}

適用於SpringBoot的簡化版工具類

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);
    }

}

SpringBoot+表單上傳測試

前端代碼

<!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);
    }

}


免責聲明!

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



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