项目接入阿里云oss对象云存储采用获取签名方式对比优化

前言

今天本来在写项目的时候接入oss对象云存储的功能来减轻服务的压力。

采用的是从后台获取签名直接发送给阿里云存储服务器,这样就需要经过我们自己的服务器,减轻了服务器的压力

首先我们准备的环境是根据alibaba提供的官方提供的一个案例来跟着写的官方演示文档,然后就是各种报错,因为版本的不兼容,还有一些版本里面的依赖冲突,这些都是一些诟病,又是换别人可以但是你又不可以了,我就是属于各种报错的人,太难了。。。。

资源

阿里云官方提供的sdk示例授权第三方上传
这个也是阿里巴巴提供的在git上面的注解示例

这里解释一下,就是一个需要我们去配置一下oss的配置,一个就是直接使用alibaba(git)的依赖直接使用(这个只要把它里面需要的参数配置在你的配置文件里面即可)

阿里云官方提供的各种骚操作api的文档,有兴趣的朋友可以去看看API参考文档

开始操作,干

使用注解方式配置

pom文件

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>aliyun-oss-spring-boot-starter</artifactId>
</dependency>

配置文件(来看这个文章的估计这个里面的参数都懂如果不是很清楚的话在这里给一个链接去看看官方解释

alibaba.cloud.access-key=your-ak
alibaba.cloud.secret-key=your-sk
alibaba.cloud.oss.endpoint=*** 

测试类 就是在这里直接使用注解的方式直接注入,不需要其他的配置了

 @Service
 public class YourService {
 	@Autowired
 	private OSSClient ossClient; 

 	public void saveFile() {
 		// download file to local
 		ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File("pathOfYourLocalFile"));
 	}
 }

到这里这个示例就结束了,你们可以自己去配置看看,后续…

使用配置的方式

pom文件(这里针对java8)

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.1</version>
</dependency>

如果使用的是java9及以上的版本,则还需要添加jaxb相关依赖

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>

配置文件.yml格式的;

oss:
  access-key: 不告诉你
  secret-key: 你问我我也不说
  endpoint: 气死你
  bucket: 去阿里云控制台自己获取

示例代码:(你自己可以在这里做一些其他的操作例如给每个文件一个uuid来区分文件或者一个分类管理,然后自己去拼接一下下载路径,存在数据库)

@SpringBootTest
class MallThirdPartyApplicationTests {

    @Value("${oss.accesskey}")
    private  String ak;
    @Value("${oss.secretkey}")
    private  String sk;
    @Value("${oss.endpoint}")
    private  String endpoint;
    @Value("${oss.bucket}")
    private  String bucket ;


    @Test
    void contextLoads() throws FileNotFoundException {
        OSS ossClient = new OSSClientBuilder().build(endpoint, ak, sk);

        InputStream inputStream = new FileInputStream("你要上传的文件路径");

        ossClient.putObject(bucket, "上传到服务器的名字", inputStream);
        System.out.println("上传成功");
    }

我这里给一个我自己整合的,写的不好不要见怪,这里的参数获取(可以采纳上面的方式)

    @Value("${oss.accesskey}")
    private  String ak;
    @Value("${oss.secretkey}")
    private  String sk;
    @Value("${oss.endpoint}")
    private  String endpoint;
    @Value("${oss.bucket}")
    private  String bucket ;

/**
     * @description 对文件做出一些处理
     * @author 沐光
     */
public ResponseResult<T> uploadImg(MultipartFile img) {
        // 判断文件类型 获取原始文件名
        String originalFilename = img.getOriginalFilename();
        System.err.println(originalFilename);
        // 对原始文件名进行判断 如果不是我需要的类型就抛出错误
        if (originalFilename != null && !originalFilename.endsWith(".png") && !originalFilename.endsWith(".jpg")) {
            throw new SystemException("请上传以.png、.jpg结尾得图片");
        }
        // 对文件名做出处理 
        String filePath = generateFilePath(originalFilename);
        // 上传文件 成功后会返回一个下载路径
        String downPath = uploadOss(img, filePath);
        if (!StringUtils.hasText(downPath)) {
            throw new SystemException("上传失败");
        }

        return ResponseResult.okResult(downPath);
    }


	/**
     * @description 连接阿里云oss并且上传数据
     * @author 沐光
     * @return 这里的返回值就是我们文件的下载路径
     */
private String uploadOss(MultipartFile imgFile, String filePath){
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream = imgFile.getInputStream();
            // 创建PutObject请求。
            ossClient.putObject(bucketName, filePath, inputStream);
            return new StringBuilder(downHeader)
                    .append(filePath).toString();
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (Exception ce) {
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }
		/**
		  返回的结果示例:/年/月/0204c061c8e90943ebab399e0cc89e2a6e.jpg
		* @author 沐光
		*/
private String generateFilePath(String fileName){
        // 根据日期生成路径
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String dataPath = sdf.format(new Date()); // .replace("/","")
        // uuid作为文件名 替换其中得 -
        String uuid = UUID.randomUUID().toString().replace("-", "");
        // 后缀名和文件后缀一致 lastIndexOf:返回指定字符最后一次出现得索引
        int index = fileName.lastIndexOf(".");
        String fileType = fileName.substring(index);
        return new StringBuilder().append(dataPath).append(uuid).append(fileType).toString();
    }

到这里基本的oss操作你们就学会了

采用获取签名的方式来上传

接下里直接到重头戏了,我们采用从后台获取签名的方式来上传,这样减轻了服务器的压力,造成不必要的资源浪费

还是先给出阿里的官方文档官方示例, 我也是参考这里写出来的

直接上我的过程,我才用的还是需要配置的,因为使用注解的,好像有本版依赖冲突,所以为了不必要的麻烦。我直接使用配置版的,大家可以参考一下自己去实践一下

pom文件

		<!--阿里云对象存储-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.17.1</version>
        </dependency>

配置文件

oss:
  access-key: bugaosuni
  secret-key: wenwowoyebushuo
  endpoint: qisini
  bucket: 去阿里云里面获取
  host: https://你的bucket+.+你的endpoint

示例代码:

/**
 * description : 对象云存储服务
 *
 * @author : 沐光
 * @date : 2023-12-02
 */
@RestController
public class OssController {

    @Value("${oss.access-key}")
    private String accessId;
    @Value("${oss.secret-key}")
    private String accessKey;
    @Value("${oss.endpoint}")
    private String endpoint;
    @Value("${oss.bucket}")
    private String bucket;
    @Value("${oss.host}")
    private String host;

    @RequestMapping("/oss/policy")
    public R GetPolicy() {
        // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        //year
        simpleDateFormat.applyPattern("yyyy");
        String year = simpleDateFormat.format(new Date());
        //date
        simpleDateFormat.applyPattern("MM/dd");
        String date = simpleDateFormat.format(new Date());
        //directory
        String dir = year + "/" + date;

        // 创建ossClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
        Map<String, String> respMap = new LinkedHashMap<String, String>();

        try {
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            // 文件的存储路径
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            // respMap.put("expire", formatISO8601Date(expiration));

        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        }
        return R.ok().put("data", respMap);
    }
}

从前前端的获取结果就是:

这里面的信息就是你可以直接从前端发送请求到oss服务器

记过描述

到这里结束了我的分享,当然我想到这里,还有很多小伙伴需要前端代码这里我也封装好了一个前端.vue 的组件。链接地址如下(如果链接失效可以私信我)
结构图

链接地址如下:
链接:https://pan.baidu.com/s/1COc1IaODRYu7O-xZrfnX2A?pwd=0156
提取码:0156

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值