寫一個簡單的阿里云OSS上傳器-利用建造者模式和適配器模式

寫一個簡單的阿里云OSS上傳器-利用建造者模式和適配器模式

代碼鏈接

最近寫一個 阿里云OSS 上傳文件的工具類 支持 InputStreamFile 等形式的文件上傳到 阿里云OSS 然后再處理返回值

OSSUtil設(shè)計思路:

  1. .xls .xlsx 文件調(diào)用 InputStream 的方法
  2. String , .html , .jpg 可以轉(zhuǎn)為 InputStream , 調(diào)用 InputStream 重載方法
  3. 文件調(diào)用 File 的方法
  4. 文件名轉(zhuǎn)為 File 重載 File 的方法
  5. 構(gòu)造上傳參數(shù)
  6. 上傳文件
  7. 處理返回值 生成包裝對象返回給調(diào)用方

public OssFileRes ossUpload(OssType ossType, Document document, String path, String fileName) {
    String html = document.html();

    InputStream inputStream = new ByteArrayInputStream(html.getBytes());
    return ossUpload(ossType, inputStream, path, fileName, FileType.html);
}
    
public OssFileRes ossUpload(OssType ossType, String file, String path, String fileName) {
    InputStream inputStream = new ByteArrayInputStream(file.getBytes());
    return ossUpload(ossType, inputStream, path, fileName, FileType.txt);
}

public OssFileRes ossUpload(OssType ossType, File file, String path, String fileName, FileType fileType) {
    OSSClient ossClient = new OSSClient(aliyunOssConfig.getEndpoint(), aliyunOssConfig
            .getAccessKeyId(), aliyunOssConfig.getAccessKeySecret());
    OssFileRes ossFile = new OssFileRes();

    try {
        // 上傳文件代碼 略
    } catch (OSSException oe) {
        log.error(ExceptionCode.ALI_OSS_OPEN_STORAGE_SERVICE_ERROR.getMsg());
    } catch (ClientException ce) {
        log.error(ExceptionCode.ALI_OSS_REMOTE_ERROR.getMsg());
    } finally {
        //關(guān)閉ossClient
        ossClient.shutdown();
    }

    // 包裝返回值
    ossFile.setKey(key);
    ossFile.setUrl(aliyunOssConfig.getServerUrl() + key);
    return ossFile;
}

public OssFileRes ossUpload(OssType ossType, InputStream inputStream, String path, String fileName, FileType fileType) {
    OSSClient ossClient = new OSSClient(aliyunOssConfig.getEndpoint(), aliyunOssConfig
            .getAccessKeyId(), aliyunOssConfig.getAccessKeySecret());
    OssFileRes ossFile = new OssFileRes();

    try {
        // 上傳文件代碼 略
    } catch (OSSException oe) {
        log.error(ExceptionCode.ALI_OSS_OPEN_STORAGE_SERVICE_ERROR.getMsg());
    } catch (ClientException ce) {
        log.error(ExceptionCode.ALI_OSS_REMOTE_ERROR.getMsg());
    } finally {
        //關(guān)閉ossClient
        ossClient.shutdown();
    }

    // 包裝返回值
    ossFile.setKey(key);
    ossFile.setUrl(aliyunOssConfig.getServerUrl() + key);
    return ossFile;
}

這里面就遇到了一些問題:

InputStreamFile 上傳是兩個重載的方法 需要構(gòu)造上傳參數(shù)并處理返回值 這里面就出現(xiàn)了重復(fù)的代碼 需要把這部分構(gòu)造上傳參數(shù)和上傳功能寫成上傳器 然后兩個方法調(diào)用上傳的重載方法 然后再調(diào)用處理返回值的部分

改造后的方案:

/**
 * 使用 Uploader 包裝 File 上傳到 阿里云oss
 *
 * @param ossType  使用場景
 * @param file     文件
 * @param path     oss 路徑
 * @param fileName oss 文件名
 * @param fileType oss 文件拓展名
 * @return 返回路徑鏈接狀態(tài)
 */
public OssFileRes ossUpload(OssType ossType, File file, String path, String fileName, FileType fileType) {
    UploadPathBuilder uploadPathBuilder = new TimeStampPathBuilder(ossType, path, fileName, fileType);
    Uploader uploader = new FileUploader(file, uploadPathBuilder);
    return ossUpload(uploader);
}

/**
 * 使用 Uploader 包裝 InputStream 上傳到 阿里云oss
 *
 * @param ossType     使用場景
 * @param inputStream 流
 * @param path        oss 路徑
 * @param fileName    oss 文件名
 * @param fileType    oss 文件拓展名
 * @return 返回路徑鏈接狀態(tài)
 */
public OssFileRes ossUpload(OssType ossType, InputStream inputStream, String path, String fileName, FileType fileType) {
    UploadPathBuilder uploadPathBuilder = new TimeStampPathBuilder(ossType, path, fileName, fileType);
    Uploader uploader = new InputStreamUploader(inputStream, uploadPathBuilder);
    return ossUpload(uploader);
}

/**
 * 通過上傳器上傳文件到 阿里云oss
 *
 * @param uploader 上傳器
 * @return 返回路徑鏈接狀態(tài)
 */
public OssFileRes ossUpload(Uploader uploader) {
    String key = "/" + uploader.getUploadPath();
    OSSClient ossClient = new OSSClient(aliyunOssConfig.getEndpoint(), aliyunOssConfig
            .getAccessKeyId(), aliyunOssConfig.getAccessKeySecret());
    OssFileRes ossFile = new OssFileRes();

    try {
        uploader.upload(ossClient, aliyunOssConfig.getBucketName());
    } catch (OSSException oe) {
        log.error(ExceptionCode.ALI_OSS_OPEN_STORAGE_SERVICE_ERROR.getMsg());
    } catch (ClientException ce) {
        log.error(ExceptionCode.ALI_OSS_REMOTE_ERROR.getMsg());
    } finally {
        //關(guān)閉ossClient
        ossClient.shutdown();
    }

    ossFile.setKey(key);
    ossFile.setUrl(aliyunOssConfig.getServerUrl() + key);
    return ossFile;
}

上傳器設(shè)計:

  1. 上傳路徑建造者接口: UploaderPathBuilder
  2. 利用時間戳生成上傳路徑: TimeStampPathBuilder
  3. 上傳器接口: Uploader
  4. 抽象上傳器: AbstractUploader
  5. 文件上傳器: FileUploader
  6. 流上傳器: InputStreamUploader

代碼鏈接

上傳器接口, 包括上傳和獲取上傳路徑

/**
 * oss上傳器接口
 */
public interface Uploader {
    // 上傳方法
    void upload(OSSClient ossClient, String bucketName);

    // 獲取上傳路徑
    String getUploadPath();
}


構(gòu)造上傳參數(shù)的 Builder 接口

/**
 * 上傳地址建造者
 *
 * @author colagy
 */
public interface UploadPathBuilder {
    String build();
}


利用時間戳生成上傳參數(shù)

public class TimeStampPathBuilder implements UploadPathBuilder {

    private OssType ossType;
    private String path;
    private String fileName;
    private FileType fileType;

    public TimeStampPathBuilder(OssType ossType, String path, String fileName, FileType fileType) {
        this.ossType = ossType;
        this.path = path;
        this.fileName = fileName;
        this.fileType = fileType;
    }

    @Override
    /**
     *
     * 上傳路徑 builder
     *
     * @param ossType  對象類型
     * @param path     路徑
     * @param fileName 文件名
     * @param fileType 文件拓展名
     * @return key
     */
    public String build() {
        if (Objects.isNull(fileType)) {
            fileType = FileType.txt;
        }
        LocalDateTime localDateTime = LocalDateTime.now();
        String year = localDateTime.getYear() + "";
        String month = localDateTime.getMonthValue() + "";
        if (month.length() < 2) {
            month = "0" + month;
        }
        String day = localDateTime.getDayOfMonth() + "";
        if (day.length() < 2) {
            day = "0" + day;
        }
        String hour = localDateTime.getHour() + "";
        if (hour.length() < 2) {
            hour = "0" + hour;
        }
        String minute = localDateTime.getMinute() + "";
        if (minute.length() < 2) {
            minute = "0" + minute;
        }
        String second = localDateTime.getSecond() + "";
        if (second.length() < 2) {
            second = "0" + second;
        }
        String millisecond = localDateTime.getNano() / 1000000 + "";


        //以時間戳對文件進行重命名,以免文件沖突
        String uploadPath =
                ossType.type + "/" + path + year + "_" + month + "_" + day + "/" +
                        hour + "_" + minute + "_" + second + "_" + millisecond + "_" + fileName + fileType.type;
        return uploadPath;
    }

}


抽象上傳器默認(rèn)調(diào)用上傳參數(shù)建造者

/**
 * 抽象上傳器
 *
 * @author 王旭
 * @version 1.0
 */
public abstract class AbstractUploader implements Uploader {
    // 上傳路徑
    protected String uploadPath;
    // 上傳客戶端
    protected OSSClient ossClient;
    // 路徑建造者
    protected UploadPathBuilder uploadPathBuilder;

    /**
     * 構(gòu)造器
     *
     * @param uploadPath 上傳路徑
     */
    AbstractUploader(String uploadPath) {
        this.uploadPath = uploadPath;
    }

    AbstractUploader(UploadPathBuilder uploadPathBuilder) {
        this.uploadPathBuilder = uploadPathBuilder;
        uploadPathBuilder.build();
    }

    public String getUploadPath() {
        return uploadPath;
    }

    public void buildUploadPath() {
        uploadPath = uploadPathBuilder.build();
    }
}


文件上傳器

/***
 * @author 王旭
 * @version 1.0
 * 文件上傳器
 */
public class FileUploader extends AbstractUploader {
    // 文件
    private File file;

    /**
     * @param file       文件
     * @param uploadPath 路徑
     */
    public FileUploader(File file, String uploadPath) {
        super(uploadPath);
        this.file = file;
    }

    public FileUploader(File file, UploadPathBuilder uploadPathBuilder) {
        super(uploadPathBuilder);
        this.file = file;
    }

    /**
     * 上傳文件
     *
     * @param ossClient  客戶端
     * @param bucketName 儲存名
     */
    @Override
    public void upload(OSSClient ossClient, String bucketName) {
        ossClient.putObject(bucketName, uploadPath, file);
    }
}


流式文件上傳

/***
 * @author 王旭
 * @version 1.0
 * 流上傳
 */
public class InputStreamUploader extends AbstractUploader {
    // 輸入流
    private InputStream inputStream;

    /**
     * @param inputStream 輸入流
     * @param uploadPath  路徑
     */
    public InputStreamUploader(InputStream inputStream, String uploadPath) {
        super(uploadPath);
        this.inputStream = inputStream;
    }

    public InputStreamUploader(InputStream inputStream, UploadPathBuilder uploadPathBuilder) {
        super(uploadPathBuilder);
        this.inputStream = inputStream;
    }

    /**
     * 輸入流上傳
     *
     * @param ossClient  客戶端
     * @param bucketName 儲存名
     */
    @Override
    public void upload(OSSClient ossClient, String bucketName) {
        ossClient.putObject(bucketName, uploadPath, inputStream);
    }
}

目前實現(xiàn)的一個簡單的上傳器, 滿足了目前項目的需要, 回頭要重新設(shè)計一個這個上傳器, 滿足更多的需求.
如果有些的不好的地方希望大家來噴

代碼鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市翰铡,隨后出現(xiàn)的幾起案子安吁,更是在濱河造成了極大的恐慌,老刑警劉巖公浪,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件收壕,死亡現(xiàn)場離奇詭異歼捐,居然都是意外死亡,警方通過查閱死者的電腦和手機你画,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門抵碟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坏匪,你說我怎么就攤上這事拟逮。” “怎么了适滓?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵敦迄,是天一觀的道長。 經(jīng)常有香客問我,道長罚屋,這世上最難降的妖魔是什么苦囱? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮脾猛,結(jié)果婚禮上撕彤,老公的妹妹穿的比我還像新娘。我一直安慰自己猛拴,他們只是感情好羹铅,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著愉昆,像睡著了一般职员。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撼唾,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天廉邑,我揣著相機與錄音,去河邊找鬼倒谷。 笑死蛛蒙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的渤愁。 我是一名探鬼主播牵祟,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼抖格!你這毒婦竟也來了诺苹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤雹拄,失蹤者是張志新(化名)和其女友劉穎收奔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滓玖,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡坪哄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了势篡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翩肌。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖禁悠,靈堂內(nèi)的尸體忽然破棺而出念祭,到底是詐尸還是另有隱情,我是刑警寧澤碍侦,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布粱坤,位于F島的核電站隶糕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏站玄。R本人自食惡果不足惜若厚,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜒什。 院中可真熱鬧,春花似錦疤估、人聲如沸灾常。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钞瀑。三九已至,卻和暖如春慷荔,著一層夾襖步出監(jiān)牢的瞬間雕什,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工显晶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贷岸,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓磷雇,卻偏偏與公主長得像偿警,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子唯笙,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容