写一个简单的阿里云OSS上传器-利用建造者模式和适配器模式
最近写一个 阿里云OSS
上传文件的工具类 支持 InputStream
和 File
等形式的文件上传到 阿里云OSS
然后再处理返回值
OSSUtil设计思路:
-
.xls
.xlsx
文件调用InputStream
的方法 -
String
,.html
,.jpg
可以转为InputStream
, 调用InputStream
重载方法 - 文件调用
File
的方法 - 文件名转为
File
重载File
的方法 - 构造上传参数
- 上传文件
- 处理返回值 生成包装对象返回给调用方
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 {
//关闭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 {
//关闭ossClient
ossClient.shutdown();
}
// 包装返回值
ossFile.setKey(key);
ossFile.setUrl(aliyunOssConfig.getServerUrl() + key);
return ossFile;
}
这里面就遇到了一些问题:
InputStream
和 File
上传是两个重载的方法 需要构造上传参数并处理返回值 这里面就出现了重复的代码 需要把这部分构造上传参数和上传功能写成上传器 然后两个方法调用上传的重载方法 然后再调用处理返回值的部分
改造后的方案:
/**
* 使用 Uploader 包装 File 上传到 阿里云oss
*
* @param ossType 使用场景
* @param file 文件
* @param path oss 路径
* @param fileName oss 文件名
* @param fileType oss 文件拓展名
* @return 返回路径链接状态
*/
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 返回路径链接状态
*/
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 返回路径链接状态
*/
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 {
//关闭ossClient
ossClient.shutdown();
}
ossFile.setKey(key);
ossFile.setUrl(aliyunOssConfig.getServerUrl() + key);
return ossFile;
}
上传器设计:
- 上传路径建造者接口:
UploaderPathBuilder
- 利用时间戳生成上传路径:
TimeStampPathBuilder
- 上传器接口:
Uploader
- 抽象上传器:
AbstractUploader
- 文件上传器:
FileUploader
- 流上传器:
InputStreamUploader
上传器接口, 包括上传和获取上传路径
/**
* oss上传器接口
*/
public interface Uploader {
// 上传方法
void upload(OSSClient ossClient, String bucketName);
// 获取上传路径
String getUploadPath();
}
构造上传参数的 Builder
接口
/**
* 上传地址建造者
*
* @author colagy
*/
public interface UploadPathBuilder {
String build();
}
利用时间戳生成上传参数
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;
}
}
抽象上传器默认调用上传参数建造者
/**
* 抽象上传器
*
* @author 王旭
* @version 1.0
*/
public abstract class AbstractUploader implements Uploader {
// 上传路径
protected String uploadPath;
// 上传客户端
protected OSSClient ossClient;
// 路径建造者
protected UploadPathBuilder uploadPathBuilder;
/**
* 构造器
*
* @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);
}
}
目前实现的一个简单的上传器, 满足了目前项目的需要, 回头要重新设计一个这个上传器, 满足更多的需求.
如果有些的不好的地方希望大家来喷