文件上传后,不仅可以保存在部署应用的服务器,也可以保存在阿里云,华为云obs,本文主要分享 SpringBoot 整合这三种不同文件存储服务器的思路
1.既然要实现存储到三种不同的文件存储服务器,那自然想到接口和实现类,然后将实现类提供给 controller 调用。为了在程序中方便的知道实现类的简单类名和全类名来进行测试,可以新建一个抽象类。
接口
public interface FileService {
FileInfoVo upload(MultipartFile multipartFile);
String getSimpleClassName();
String getFullClassName();
}
抽象类
public abstract class AbstractFileServiceImpl implements FileService {
@Override
public String getSimpleClassName() {
return this.getClass().getSimpleName();
}
@Override
public String getFullClassName() {
return this.getClass().getName();
}
}
三个实现类
// 文件上传到部署应用的服务器
@Service
public class LocalFileServiceImpl extends AbstractFileServiceImpl {
@Override
public FileInfoVo upload(MultipartFile multipartFile) {
return null;
}
}
// 文件上传到阿里云
@Service
public class AliyunFileServiceImpl extends AbstractFileServiceImpl {
@Override
public FileInfoVo upload(MultipartFile multipartFile) {
return null;
}
}
// 文件上传到华为 obs
@Service
public class HuaweiObsFileServiceImpl extends AbstractFileServiceImpl {
@Override
public FileInfoVo upload(MultipartFile multipartFile) {
return null;
}
}
2.具体实现文件相关操作的逻辑如果写在 service 里,不利于程序的扩展,所以我们再新建三个工具类给 service 实现类调用,所以需要在三个 service 实现类中注入对应的工具类,同时由于在工具类中写的都是具体的功能实现逻辑,想要上传到阿里云,华为云,就需要参考官网,进行导包和相应的配置
导包
<dependency>
<groupId>com.aliyun.ossgroupId>
<artifactId>aliyun-sdk-ossartifactId>
<verison>3.15.1version>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.huaweicloudgroupId>
<artifactId>esdk-obs-java-bundleartifactId>
<verison>3.22.12version>
<optional>trueoptional>
dependency>
配置文件
# appliation.yml 文件
file:
local:
path: xxx
aliyun:
endpoint: xxx
access-key-id: xxx
access-key-secret: xxx
bucket-name: xxx
huawei-obs:
endpoint: xxx
access-key-id: xxx
access-key-secret: xxx
bucket-name: xxx
配置类
// 文件上传到部署应用的服务器的配置类
@Configuration
public class LocalFileConfig {
@Bean
public LocalFileUtil localFileUtil() {
return new LocalFileUtil();
}
}
// 文件上传到阿里云的配置类
@Configuration
public class AliyunFileConfig {
@Value("${file.aliyun.endpoint:}")
private String endpoint;
@Value("${file.aliyun.access-key-id:}")
private String accessKeyId;
@Value("${file.aliyun.access-key-secret:}")
private String accessKeySecret;
/**
* 阿里云文件存储 client
*/
@Bean
public OSSClient ossClient() {
return new OSSClient(endpoint, accessKeyId, accessKeySecret);
}
@Bean
public AliyunFileUtil aliyunFileUtil() {
return new AliyunFileUtil();
}
}
// 文件上传到华为 obs 的配置类
@Configuration
public class HuaweiObsConfig {
@Value("${file.huawei-obs.endpoint:}")
private String endpoint;
@Value("${file.huawei-obs.access-key-id:}")
private String accessKeyId;
@Value("${file.huawei-obs.access-key-secret:}")
private String accessKeySecret;
@Bean
public ObsClient obsClient() {
return new ObsClient(accessKeyId, accessKeySecret, endpoint);
}
@Bean
public HuaweiObsFileUtil huaweiObsFileUtil() {
return new HuaweiObsFileUtil();
}
}
工具类
// 文件上传到部署应用的服务器的工具类
public class LocalFileUtil {
public FileInfoVo upload(MultipartFile file) {
return null;
}
}
// 文件上传到阿里云的工具类
public class AliyunFileUtil {
@Value("${file.aliyun.bucket-name:}")
private String bucketName;
public FileInfoVo upload(MultipartFile file) {
return null;
}
}
// 文件上传到华为 obs 的工具类
public class HuaweiObsFileUtil {
@Value("${file.huawei-obs.bucket-name:}")
private String bucketName;
public FileInfoVo upload(MultipartFile file) {
return null;
}
}
service 实现类
// 文件上传到部署应用的服务器
@Service
public class LocalFileServiceImpl extends AbstractFileServiceImpl {
@Resource
private LocalFileUtil localFileUtil;
@Override
public FileInfoVo upload(MultipartFile multipartFile) {
// 自己写具体的上传逻辑
return localFileUtil.upload(multipartFile);
}
}
// 文件上传到阿里云
@Service
public class AliyunFileServiceImpl extends AbstractFileServiceImpl {
@Resource
private AliyunFileUtil aliyunFileUtil;
@Override
public FileInfoVo upload(MultipartFile multipartFile) {
// 参考阿里云示例程序写具体的上传逻辑
return aliyunFileUtil.upload(multipartFile);
}
}
// 文件上传到华为 obs
@Service
public class HuaweiObsFileServiceImpl extends AbstractFileServiceImpl {
@Resource
private HuaweiObsFileUtil huaweiObsFileUtil;
@Override
public FileInfoVo upload(MultipartFile multipartFile) {
// 参考华为云 obs 示例程序写具体的上传逻辑
return huaweiObsFileUtil.upload(multipartFile);
}
}
3.这样就可以在 controller 中注入三个实现类来调用方法了,当然为了后续扩展方便,可以通过 factory 类和枚举类来获得 service 实现类,然后在 controller 中注入 factory 类,通过 factory 来获得 service 实现类
枚举类
@Getter
public enum FileUploadTypeEnum {
LOCAL("0", FileConstants.LOCAL_FILE_SERVICE_BEAN),
ALIYUN("1", FileConstants.ALIYUN_FILE_SERVICE_BEAN),
HUAWEI_OBS("2", FileConstants.HUAWEI_OBS_FILE_SERVICE_BEAN);
private final String code;
private final String desc;
FileUploadTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static FileUploadTypeEnum getFileUploadTypeEnumByCode(String code) {
for (FileUploadTypeEnum fileUploadTypeEnum : FileUploadTypeEnum.values()) {
if (fileUploadTypeEnum.getCode().equals(code)) {
return fileUploadTypeEnum;
}
}
return null;
}
}
常量类
public interface FileConstants {
// FileService 实例 值为 beanName
String LOCAL_FILE_SERVICE_BEAN = "localFileServiceImpl";
String ALIYUN_FILE_SERVICE_BEAN = "aliyunFileServiceImpl";
String HUAWEI_OBS_FILE_SERVICE_BEAN = "huaweiObsFileServiceImpl";
}
factory 类
@Component
public class FileServiceFactory {
// beanMap 的结构: key: beanName value: FileService 实例
private Map<String, FileService> beanMap = new HashMap<>();
@Resource
private ApplicationContextUtil applicationContextUtil;
@PostConstruct
private void initFileService() {
beanMap = applicationContextUtil.getApplicationContext().getBeansOfType(FileService.class);
}
public FileService getFileService(FileUploadTypeEnum typeEnum) {
return beanMap.get(typeEnum.getDesc());
}
}
ApplicationContextUtil
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return this.applicationContext;
}
}
4.在 controller 中通过 factory 来获取 service 实例,调用相关方法。
以上就是本文的全部内容,希望对大家有所帮助,如有错误欢迎指正!!!