寫一個簡單的阿里云OSS上傳器-利用建造者模式和適配器模式
最近寫一個 阿里云OSS
上傳文件的工具類 支持 InputStream
和 File
等形式的文件上傳到 阿里云OSS
然后再處理返回值
OSSUtil設(shè)計思路:
-
.xls
.xlsx
文件調(diào)用InputStream
的方法 -
String
,.html
,.jpg
可以轉(zhuǎn)為InputStream
, 調(diào)用InputStream
重載方法 - 文件調(diào)用
File
的方法 - 文件名轉(zhuǎn)為
File
重載File
的方法 - 構(gòu)造上傳參數(shù)
- 上傳文件
- 處理返回值 生成包裝對象返回給調(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;
}
這里面就遇到了一些問題:
InputStream
和 File
上傳是兩個重載的方法 需要構(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è)計:
- 上傳路徑建造者接口:
UploaderPathBuilder
- 利用時間戳生成上傳路徑:
TimeStampPathBuilder
- 上傳器接口:
Uploader
- 抽象上傳器:
AbstractUploader
- 文件上傳器:
FileUploader
- 流上傳器:
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è)計一個這個上傳器, 滿足更多的需求.
如果有些的不好的地方希望大家來噴