SpringBoot实现云存储功能
一、引入相应云平台SDK
<dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>${qiniu.version}</version> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>${aliyun.oss.version}</version> </dependency> <dependency> <groupId>com.qcloud</groupId> <artifactId>cos_api</artifactId> <version>${qcloud.cos.version}</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency>
二、定义抽象类 CloudStorageService ,用来声明上传的公共接口,如下所示:
/** * 云存储(支持七牛、阿里云、腾讯云、又拍云) * */ public abstract class CloudStorageService { /** 云存储配置信息 */ CloudStorageConfig config; /** * 文件路径 * @param prefix 前缀 * @param suffix 后缀 * @return 返回上传路径 */ public String getPath(String prefix, String suffix) { //生成uuid String uuid = UUID.randomUUID().toString().replaceAll("-", ""); //文件路径 String path = DateUtils.format(new Date(), "yyyyMMdd") + "/" + uuid; if(StringUtils.isNotBlank(prefix)){ path = prefix + "/" + path; } return path + suffix; } /** * 文件上传 * @param data 文件字节数组 * @param path 文件路径,包含文件名 * @return 返回http地址 */ public abstract String upload(byte[] data, String path); /** * 文件上传 * @param data 文件字节数组 * @param suffix 后缀 * @return 返回http地址 */ public abstract String uploadSuffix(byte[] data, String suffix); /** * 文件上传 * @param inputStream 字节流 * @param path 文件路径,包含文件名 * @return 返回http地址 */ public abstract String upload(InputStream inputStream, String path); /** * 文件上传 * @param inputStream 字节流 * @param suffix 后缀 * @return 返回http地址 */ public abstract String uploadSuffix(InputStream inputStream, String suffix); }
三、
1、七牛上传的实现,只需继承 CloudStorageService ,并实现相应的上传接口,如下所示:
/** * 七牛云存储 * */ public class QiniuCloudStorageService extends CloudStorageService { private UploadManager uploadManager; private String token; public QiniuCloudStorageService(CloudStorageConfig config){ this.config = config; //初始化 init(); } private void init(){ uploadManager = new UploadManager(new Configuration(Zone.autoZone())); token = Auth.create(config.getQiniuAccessKey(), config.getQiniuSecretKey()). uploadToken(config.getQiniuBucketName()); } @Override public String upload(byte[] data, String path) { try { Response res = uploadManager.put(data, path, token); if (!res.isOK()) { throw new RuntimeException("上传七牛出错:" + res.toString()); } } catch (Exception e) { throw new RRException("上传文件失败,请核对七牛配置信息", e); } return config.getQiniuDomain() + "/" + path; } @Override public String upload(InputStream inputStream, String path) { try { byte[] data = IOUtils.toByteArray(inputStream); return this.upload(data, path); } catch (IOException e) { throw new RRException("上传文件失败", e); } } @Override public String uploadSuffix(byte[] data, String suffix) { return upload(data, getPath(config.getQiniuPrefix(), suffix)); } @Override public String uploadSuffix(InputStream inputStream, String suffix) { return upload(inputStream, getPath(config.getQiniuPrefix(), suffix)); } }
2、腾讯云上传的实现,只需继承 CloudStorageService ,并实现相应的上传接口,如下所示:
/** * 腾讯云存储 * */ public class QcloudCloudStorageService extends CloudStorageService { private COSClient client; public QcloudCloudStorageService(CloudStorageConfig config){ this.config = config; //初始化 init(); } private void init(){ Credentials credentials = new Credentials(config.getQcloudAppId(), config.getQcloudSecretId(), config.getQcloudSecretKey()); //初始化客户端配置 ClientConfig clientConfig = new ClientConfig(); //设置bucket所在的区域,华南:gz 华北:tj 华东:sh clientConfig.setRegion(config.getQcloudRegion()); client = new COSClient(clientConfig, credentials); } @Override public String upload(byte[] data, String path) { //腾讯云必需要以"/"开头 if(!path.startsWith("/")) { path = "/" + path; } //上传到腾讯云 UploadFileRequest request = new UploadFileRequest(config.getQcloudBucketName(), path, data); String response = client.uploadFile(request); JSONObject jsonObject = JSONObject.parseObject(response); if(jsonObject.getInteger("code") != 0) { throw new RRException("文件上传失败," + jsonObject.getString("message")); } return config.getQcloudDomain() + path; } @Override public String upload(InputStream inputStream, String path) { try { byte[] data = IOUtils.toByteArray(inputStream); return this.upload(data, path); } catch (IOException e) { throw new RRException("上传文件失败", e); } } @Override public String uploadSuffix(byte[] data, String suffix) { return upload(data, getPath(config.getQcloudPrefix(), suffix)); } @Override public String uploadSuffix(InputStream inputStream, String suffix) { return upload(inputStream, getPath(config.getQcloudPrefix(), suffix)); } }
3、腾讯云上传的实现,只需继承 CloudStorageService ,并实现相应的上传接口,如下所示:
/** * 阿里云存储 * */ public class AliyunCloudStorageService extends CloudStorageService { private OSSClient client; public AliyunCloudStorageService(CloudStorageConfig config){ this.config = config; //初始化 init(); } private void init(){ client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(), config.getAliyunAccessKeySecret()); } @Override public String upload(byte[] data, String path) { return upload(new ByteArrayInputStream(data), path); } @Override public String upload(InputStream inputStream, String path) { try { client.putObject(config.getAliyunBucketName(), path, inputStream); } catch (Exception e){ throw new RRException("上传文件失败,请检查配置信息", e); } return config.getAliyunDomain() + "/" + path; } @Override public String uploadSuffix(byte[] data, String suffix) { return upload(data, getPath(config.getAliyunPrefix(), suffix)); } @Override public String uploadSuffix(InputStream inputStream, String suffix) { return upload(inputStream, getPath(config.getAliyunPrefix(), suffix)); } }
四、对外提供了OSSFactory工厂,可方便业务的调用,如下所示:
/** * 文件上传Factory * */ public final class OSSFactory { private static SysConfigService sysConfigService; static { OSSFactory.sysConfigService = (SysConfigService) SpringContextUtils.getBean("sysConfigService"); } public static CloudStorageService build(){ //获取云存储配置信息 CloudStorageConfig config = sysConfigService.getConfigObject(ConfigConstant.CLOUD_STORAGE_CONFIG_KEY, CloudStorageConfig.class); if(config.getType() == Constant.CloudService.QINIU.getValue()){ return new QiniuCloudStorageService(config); }else if(config.getType() == Constant.CloudService.ALIYUN.getValue()){ return new AliyunCloudStorageService(config); }else if(config.getType() == Constant.CloudService.QCLOUD.getValue()){ return new QcloudCloudStorageService(config); } return null; } }
五、文件上传的例子,如下:
/** * 上传文件 */ @PostMapping("/upload") @RequiresPermissions("sys:oss:all") public R upload(@RequestParam("file") MultipartFile file) throws Exception { if (file.isEmpty()) { throw new RRException("上传文件不能为空"); } //获取上传文件后缀 String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")); //上传到aliyun/qiniucloud/Qcloud,并返回地址url String url = OSSFactory.build().uploadSuffix(file.getBytes(), suffix); //保存文件信息 SysOssEntity ossEntity = new SysOssEntity(); ossEntity.setUrl(url); ossEntity.setCreateDate(new Date()); sysOssService.save(ossEntity); return R.ok().put("url", url); }
一个小小后端的爬行痕迹