JAVA集成阿里云OSS对象存储

JAVA集成阿里云OSS对象存储

  • 1 : 配置集成
    • 1.1、对象存储OSS
  • 2 : 代码配置
    • 2.1、说明
    • 2.2、配置文件
    • 2.3、加载配置文件代码
    • 2.4、封装统一的DTO
    • 2.5、OSS上传Controller
    • 2.6、OSS上传Service
    • 2.7、OSS上传ServiceImpl
  • 3 : 测试
    • 3.1、文件上传
    • 3.2、文件迁移
  • 4 : 总结
    • 4.1、参考资料
    • 4.2、注意事项
    • 4.3、源码链接

1 : 配置集成

1.1、对象存储OSS

这就不用说了,从阿里云平台花钱买OSS对象存储就行了。
然后在bucket列表中创建自己使用的bucket即可。
比如创建:oss-test
然后从概览中找到 Access Key
在这里插入图片描述
在这里插入图片描述
然后就可以看到对应的id和key了。
在这里插入图片描述

这个时候,就有了四个参数
1、access-key:就是刚才的 AccessKey ID
2、secret-key:页面点击‘查看 Secret’就能看的到了
3、bucket:新建的桶的名称oss-test
4、endpoint:页面截图,选择自己的桶就能看到对应的endpoint

2 : 代码配置

2.1、说明

本篇代码,主要做的两件事:
1、文件上传至OSS
2、对服务器磁盘文件转存至OSS

2.2、配置文件

在application.yml中增加配置

#阿里云oss
alibaba:cloud:access-key: **********secret-key: **********oss:endpoint: oss********.aliyuncs.combucket: *******config:# oss开关 0:关  1:开oss-switch: 1# oss 开始使用时间oss-date: 2022-01-01# oss 文件夹目录oss-directory: image,attach,video,audio,template# oss titleoss-title: https://# oss business directorybusiness-directory: user,org

非常非常重要在配置的时候上面4个重要参数的位置,以及名称一定不能修改,否则会报找不到endPoint的错

2.3、加载配置文件代码

新建 YmlConfigBean.java

package com.upload.bean;import org.springframework.stereotype.Component;
import java.util.List;/*** 配置文件参数读取*/
@Component
public class YmlConfigBean {// 阿里云OSS 申请的 key idpublic volatile static String OSS_KEY_ID;// 阿里云OSS 申请的 key secretpublic volatile static String OSS_KEY_SECRET;// 阿里云OSS endpointpublic volatile static String OSS_ENDPOINT;// 阿里云OSS bucketpublic volatile static String OSS_BUCKET;// 阿里云OSS 开关 0 关 1 开public volatile static String OSS_SWITCH;// 阿里云OSS 开始使用时间public volatile static String OSS_DATE;// 阿里云OSS 文件夹目录public volatile static List<String> OSS_DIRECTORY;// 阿里云OSS 开始使用时间public volatile static String OSS_TITLE;//业务文件类别public volatile static List<String> BUSINESS_DIRECTORY;
}

新建 YmlConfigBeanMethod.java

package com.upload.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;@Component
public class YmlConfigBeanMethod {@Value("#{'${alibaba.cloud.access-key}'}")private void setOssKeyId(String key) {YmlConfigBean.OSS_KEY_ID = key;}@Value("#{'${alibaba.cloud.secret-key}'}")private void setOssKeySecret(String key) {YmlConfigBean.OSS_KEY_SECRET = key;}@Value("#{'${alibaba.cloud.oss.endpoint}'}")private void setOssEndpoint(String key) {YmlConfigBean.OSS_ENDPOINT = key;}@Value("#{'${alibaba.cloud.oss.bucket}'}")private void setOssBucket(String key) {YmlConfigBean.OSS_BUCKET = key;}@Value("#{'${alibaba.config.oss-switch}'}")private void setOssSwitch(String key) {YmlConfigBean.OSS_SWITCH = key;}@Value("#{'${alibaba.config.oss-date}'}")private void setOssDate(String key) {YmlConfigBean.OSS_DATE = key;}@Value("#{'${alibaba.config.oss-directory}'.split(',')}")public void setOssDirectory(List<String> key){YmlConfigBean.OSS_DIRECTORY = key;}@Value("#{'${alibaba.config.oss-title}'}")private void setOssTitle(String key) {YmlConfigBean.OSS_TITLE = key;}@Value("#{'${alibaba.config.business-directory}'.split(',')}")public void setBusinessDirectory(List<String> key){YmlConfigBean.BUSINESS_DIRECTORY= key;}}

2.4、封装统一的DTO

建一个统一的DTO Result.java

package com.upload.bean;/*** 统一的DTO*/
public class Result<T> {private boolean success = true;private Integer code = 0;private String msg;private T data;public boolean isSuccess() {return this.code == 0;}public void setSuccess(boolean success) {this.success = success;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;if(code != 0){success = false;}}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}public void setData(T data) {this.data = data;}public Result() {super();}public Result(boolean success) {this.success = success;if(success){code = 0;}}public Result(int code) {super();success = false;this.code = code;}public Result(String msg) {success = false;this.msg = msg;}public Result(boolean success, String msg) {super();this.success = success;this.msg = msg;}public Result(int code, String msg) {super();success = false;this.code = code;this.msg = msg;}/*设置返回为成功*/public static Result ok() {return new Result();}/*设置返回为成功,同时设置返回数据*/public Result<T> ok(T data) {Result<T> result = new Result<T>();result.setData(data);return result;}/*设置返回为失败,默认未知异常*/public static Result error() {return error(500, "未知异常,请联系管理员!");}/*设置返回为失败,同时设置异常信息*/public static Result error(String msg) {return error(500, msg);}/*设置返回为失败,同时设置code,msg*/public static Result error(Integer code,String msg) {Result result = new Result();result.setCode(code);result.setMsg(msg);return result;}public static Result<Object> error(Integer code,String msg,Object data) {Result<Object> result = new Result<Object>();result.setData(data);result.setCode(code);result.setMsg(msg);return result;}public static Result success(Object data) {Result<Object> result = new Result<Object>();result.setData(data);return result;}public static Result success(String msg) {Result result = new Result();result.setMsg(msg);return result;}}

常量配置好之后,方便后续直接使用配置文件的中内容。

2.5、OSS上传Controller

新建 OssUploadController.java

package com.upload;import com.upload.service.IOssUploadService;
import com.upload.bean.Result;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;/*** 

* 阿里云OSS 前端控制器*

*/
@Controller public class OssUploadController {@Resourceprivate IOssUploadService ossUploadService;/*** OSS文件上传*/@RequestMapping("/uploadOss")@ResponseBodypublic Result upload(@RequestParam String ossDirectory, @RequestParam String businessDirectory,@RequestParam MultipartFile file, HttpServletRequest request) {return ossUploadService.upload(ossDirectory, businessDirectory, file, request);}/*** OSS文件迁移*/@RequestMapping("/migrationOss")@ResponseBodypublic Result doDataMigration(@RequestParam String ossDirectory, @RequestParam String businessDirectory) {return ossUploadService.doDataMigration(ossDirectory, businessDirectory, true);}}

2.6、OSS上传Service

新建 IOssUploadService.java

package com.upload.service;import com.upload.bean.Result;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;/*** 

* 阿里云OSS 服务类*/ public interface IOssUploadService {Result upload(String ossDirectory, String businessDirectory, MultipartFile file, HttpServletRequest request);Result doDataMigration(String ossDirectory, String businessDirectory, boolean threadFlag);}

2.7、OSS上传ServiceImpl

新建 OssUploadServiceImpl.java

package com.upload.service.impl;import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.upload.bean.Result;
import com.upload.bean.YmlConfigBean;
import com.upload.entity.FileUpload;
import com.upload.service.IOssUploadService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;@Slf4j
@Service
public class OssUploadServiceImpl implements IOssUploadService {//    @Resource
//    private UploadMapper uploadMapper;private final static String ROOT_PATH = "/data/file/";/*** 对外提供的文件上传* @param ossDirectory OSS所属模块* @param fileDir 文件所属模块* @param file 文件* @param request 请求*/@Overridepublic Result upload(String ossDirectory, String fileDir, MultipartFile file, HttpServletRequest request) {if (file.isEmpty()) {return Result.error("不能上传空文件");}String originalFilename = file.getOriginalFilename();Long fileBytes = file.getSize();if (Strings.isBlank(originalFilename) || 0L == fileBytes) {return Result.error("不能上传空文件");}if(Strings.isBlank(ossDirectory)){ossDirectory = "image";} else {if (!YmlConfigBean.OSS_DIRECTORY.contains(ossDirectory.startsWith("/") ? ossDirectory.substring(1) : ossDirectory)) {log.info("文件上传目录非法,非法目录:"+ ossDirectory);return Result.error("文件上传目录非法,请更改文件上传目录");}}if (!YmlConfigBean.BUSINESS_DIRECTORY.contains(fileDir.startsWith("/") ? fileDir.substring(1) : fileDir)) {log.info("文件上传目录非法,非法目录:"+ fileDir);return Result.error("文件上传目录非法,请更改文件上传目录");}String fileMd5;try {fileMd5 = DigestUtils.sha256Hex(file.getInputStream());} catch (Exception e) {log.error(file.getOriginalFilename() + "验证文件md5失败",e);return Result.error("当前验证文件md5失败");}Result<String> result = new Result<>();String uploadUrl = null;String newName = null;OSS ossClient = getOSSClient();try {//获取上传文件流InputStream inputStream = file.getInputStream();//构建日期路径:/2019/02/26/文件名String fileType = originalFilename.split("\\.")[originalFilename.split("\\.").length - 1];newName = DateFormatUtils.format(new Date(), "yyMMddHHmmss") +(new SecureRandom().nextInt(100) + 100) + "." + fileType;String newFileDir = (fileDir.startsWith("/") ? fileDir.substring(1) : fileDir).trim().replace(" ","") +getDatePath();String fileUrl = ossDirectory + "/" + newFileDir + newName;// 上传文件 (上传文件流的形式)ossClient.putObject(YmlConfigBean.OSS_BUCKET, fileUrl, inputStream);//获取url地址uploadUrl = YmlConfigBean.OSS_TITLE + YmlConfigBean.OSS_BUCKET + "." + YmlConfigBean.OSS_ENDPOINT + "/" + fileUrl;} catch (IOException e) {log.error("上传OSS失败,文件名:" + originalFilename);throw new RuntimeException("上传OSS失败");} finally {// 关闭OSSClient。if (ossClient != null) {ossClient.shutdown();}}//文件上传实体属性赋值,数据入库try {log.info("原文件名称:" + originalFilename + "\n" + "文件MD5码:" + fileMd5 + "\n" + "新文件名称:" + newName + "\n" +"文件路径:" + uploadUrl + "\n" + "文件大小:" + fileBytes);
//            uploadMapper.doUploadInsert(null);} catch (Exception e) {log.error("上传文件,数据库记录失败", e);}result.setData(uploadUrl);return result;}/*** 文件迁移* @param ossDirectory 需要同步的OSS文件夹* @param businessDirectory 业务文件路径,以此查询表中数据* @param threadFlag 是否开启异步线程* @return Result*/@Overridepublic Result doDataMigration(String ossDirectory, String businessDirectory, boolean threadFlag){if(Strings.isBlank(businessDirectory)) return Result.error("路径不能为空");
//        List fileUploads = uploadMapper.selectList();List<FileUpload> fileUploads = new ArrayList<>();if(null == fileUploads || fileUploads.size() == 0) return Result.error("暂无数据");if(threadFlag){Thread thread = new Thread(()->{doSonThread(fileUploads, ossDirectory);});thread.start();} else {doSonThread(fileUploads, ossDirectory);}return Result.success("文件迁移中,请稍后查看!");}private void doSonThread(List<FileUpload> fileUploads, String ossDirectory){if(Strings.isBlank(ossDirectory)) {ossDirectory = "image";}String filePath = null;for(FileUpload fileUpload : fileUploads){if(Strings.isBlank(fileUpload.getFilePath()) || Strings.isBlank(fileUpload.getFileName())){continue;}filePath = uploadFileAndDeleteByPath(ROOT_PATH + fileUpload.getFilePath(), fileUpload.getFileName(), ossDirectory);//更新新的路径入库fileUpload.setFilePathNew(filePath);
//            uploadMapper.doUploadUpdate(fileUpload);}}public static String uploadFileAndDeleteByPath(String path, String fileName, String ossDirectory) {File file = new File(path + File.separator + fileName);return uploadFileAndDeleteByFile(file, ossDirectory);}public static String uploadFileAndDeleteByFile(File file, String ossDirectory) {if (file.isDirectory()) return null;String filePath = null;Boolean deleteFlag = false;try {filePath = uploadHistory(ossDirectory, file.getPath(), file);deleteFlag = checkExists(filePath.substring(filePath.indexOf(YmlConfigBean.OSS_ENDPOINT) + 1 + YmlConfigBean.OSS_ENDPOINT.length(), filePath.length()));} catch (IOException e) {log.error("上传OSS失败,文件名:" + file.getName());throw new RuntimeException("上传OSS失败");}if(deleteFlag){file.delete();}return filePath;}public static String uploadHistory(String ossDirectory, String businessDirectory, File file) throws IOException{String filename = file.getName();OSS ossClient = getOSSClient();//获取上传文件流InputStream inputStream = new FileInputStream(file);//构建日期路径:/2019/02/26/文件名String fileType = filename.split("\\.")[filename.split("\\.").length - 1];String newName = filename.substring(0, filename.indexOf(".")) + "_" + (new SecureRandom().nextInt(1000) + 1000) + "." + fileType;String newFileDir = (businessDirectory.startsWith("/") ? businessDirectory.substring(1) : businessDirectory).trim().replace(" ","");String fileUrl = ossDirectory + "/" + newFileDir + newName;// 上传文件 (上传文件流的形式)ossClient.putObject(YmlConfigBean.OSS_BUCKET, fileUrl, inputStream);ossClient.shutdown();//获取url地址return YmlConfigBean.OSS_TITLE + YmlConfigBean.OSS_BUCKET + "." + YmlConfigBean.OSS_ENDPOINT + "/" + fileUrl;}public static boolean checkExists(String objectName) throws IOException{OSS ossClient = getOSSClient();Boolean flag = ossClient.doesObjectExist(YmlConfigBean.OSS_BUCKET, objectName);ossClient.shutdown();return flag;}public static OSS getOSSClient() {OSS ossClient = new OSSClientBuilder().build(YmlConfigBean.OSS_ENDPOINT, YmlConfigBean.OSS_KEY_ID, YmlConfigBean.OSS_KEY_SECRET);//判断oss实例是否存在:如果不存在则创建,如果存在则获取if (!ossClient.doesBucketExist(YmlConfigBean.OSS_BUCKET)) {//创建bucketossClient.createBucket(YmlConfigBean.OSS_BUCKET);//设置oss实例的访问权限:公共读ossClient.setBucketAcl(YmlConfigBean.OSS_BUCKET, CannedAccessControlList.PublicRead);}return ossClient;}/*public static void uploadFileAndDelete(File file) {if (file.isDirectory()) {String[] fileList = file.list();if(null != fileList && fileList.length > 0){//递归删除目录中的子目录下File subFile = null;for(String str : fileList){subFile = new File(file, str);log.info(subFile.getPath());uploadFileAndDelete(subFile);}}}uploadFileAndDeleteByFile(file, null);}*/public static String getDatePath(){return "/" + DateFormatUtils.format(new Date(), "yyyy-MM-dd").replaceAll("-","/") + "/";}}

3 : 测试

3.1、文件上传

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在OSS上存储的路径为:OSS文件夹(image)+ 业务自定义文件夹名称(org)+ 年月日时间路径 + 重命名文件名称。

3.2、文件迁移

大致思路:
1、根据业务需要,查询数据库中的文件路径及名称,到服务器磁盘中查找该文件。
2、调用简易版的文件上传,上传至OSS中。
3、上传之后回调阿里自带方法doesObjectExist进行回溯校验,检查是否在OSS中存在。
4、如存在该文件,则删除服务器磁盘对应的文件即可。

因代码需根据业务数据来进行数据的查询等操作,可自行修改并验证。

4 : 总结

4.1、参考资料

参考资料:异常官网链接:https://help.aliyun.com/document_detail/32023.html

4.2、注意事项

注意事项在配置的时候上面4个重要参数的位置,以及名称一定不能修改,否则会报找不到endPoint的错

4.3、源码链接

CSDN资源链接:https://download.csdn.net/download/qq_38254635/87352781
百度网盘资源链接:https://pan.baidu.com/s/1kl6KIntr1qvcJPG642DWAA?pwd=fsj2
提取码: fsj2

有什么不对的还望指正,书写不易,觉得有帮助就点个赞吧!


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部