OSS对象存储

Posted YuanChuZiWen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OSS对象存储相关的知识,希望对你有一定的参考价值。

OSS对象存储

当项目以微服务搭建时,多个服务往往运行在多台服务器上,此时针对存储文件的获取和保存,难以确定具体的位置;

针对这个问题,一般有两个办法:

  1. 搭建独立的文件存储服务器,用 FastDFS等构建
  2. 使用第三方的对象存储 OSS,如 阿里云的 OSS

一、数据库的设计

一般数据库设计字段存储文件在上传 OSS后返回的地址值,字段宜采用 Varchar

二、后端

一般有两种用法:

  1. 前端把待传文件,先传给服务器,然后服务器传给阿里云
  2. 前端向服务器索取验证用的 Access Key等校验信息,然后独立传给 阿里云,最后再把结果传给服务器

一般使用后者

2.1、依赖

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

该依赖中包含了原始的 aliyun-sdk-oss,并且强制在配置文件中配置对象存储的信息,并且会自动创建 OSSclient对象

2.2、配置

spring:
  cloud:
    alicloud:
      access-key: LTAI5tKV72y86Xty********
      secret-key: BJXWfm4lxgc9Wv2LA2Z**********
      oss:
        endpoint: oss-cn-hangzhou.aliyuncs.com
        bucket: oliq-gulimall #这个不是默认的配置,这么写是为了方便代码里面通过 @Value()获取

2.3、使用

package com.zwb.gulimall.thirdparty.controller;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.zwb.common.utils.R;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author:OliQ
 * @date: Created on 2022-01-20 16:40
 * @description:
 */
@RestController()
@RequestMapping("/oss")
public class OSSController 

    @Resource
    private OSSClient ossClient;

    @Value("$spring.cloud.alicloud.oss.bucket")
    private String bucket;

    @Value("$spring.cloud.alicloud.oss.endpoint")
    private String endpoint;

    @Value("$spring.cloud.alicloud.access-key")
    private String accessId;


    @RequestMapping("/policy")
    public R policy() 


        String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
        // callbackUrl为上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
        // String callbackUrl = "http://88.88.88.88:8888";

        String dir = LocalDate.now().toString(); // 用户上传文件时指定的前缀。

        Map<String, String> respMap = null;

        try 
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            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 = new LinkedHashMap<String, String>();
            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());
         finally 
            ossClient.shutdown();
        

        return R.ok().put("data", respMap);
    

三、前端

主要逻辑就是:

  1. 向服务器发请求获取 验证信息
  2. 向阿里云上传数据
  3. 将文件路径交给服务器

3.1、页面组件

<template>

<div>
    <!-- action必选参数,上传地址,bucket的外网访问域名 -->
    <el-upload
               action="https://oliq-gulimall.oss-cn-hangzhou.aliyuncs.com"
               :data="dataObj"
               list-type="picture"
               :multiple="false"
               :show-file-list="showFileList"
               :file-list="fileList"
               :before-upload="beforeUpload"
               :on-remove="handleRemove"
               :on-success="handleUploadSuccess"
               :on-preview="handlePreview"
               >
        <el-button size="small" type="primary">点击上传</el-button>
        <div slot="tip" class="el-upload__tip">
            只能上传jpg/png文件,且不超过10MB
    </div>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible">
        <img  :src="fileList[0].url"  />
    </el-dialog>
    </div>
</template>

3.2、数据

data() 
    return 
        dataObj: 
            policy: "",
            signature: "",
            key: "",
            ossaccessKeyId: "",
            dir: "",
            host: "",
            // callback:\'\',
        ,
        dialogVisible: false,
    ;
,

3.3、JS

methods: 
    emitInput(val) 
      this.$emit("input", val);
    ,
        
    handleRemove(file, fileList) 
      this.emitInput("");
    ,
        
    handlePreview(file) 
      this.dialogVisible = true;
    ,
        
    beforeUpload(file) 
      let _self = this;
      return new Promise((resolve, reject) => 
        policy()
          .then((response) => 
            _self.dataObj.policy = response.data.policy;
            _self.dataObj.signature = response.data.signature;
            _self.dataObj.ossaccessKeyId = response.data.accessid;
            _self.dataObj.key =
              response.data.dir + "/" + getUUID() + "_$filename";
            _self.dataObj.dir = response.data.dir;
            _self.dataObj.host = response.data.host;
            console.log("上传前请求服务端签名,得到结果:", _self.dataObj);
            resolve(true);
          )
          .catch((err) => 
            reject(false);
          );
      );
    ,
        
    handleUploadSuccess(res, file) 
      console.log("上传成功...");
      this.showFileList = true;
      this.fileList.pop();
      this.fileList.push(
        name: file.name,
        url:
          this.dataObj.host +
          "/" +
          this.dataObj.key.replace("$filename", file.name),
      );
        
      this.emitInput(this.fileList[0].url);
    ,
  ,

请求发送代码:

import http from \'@/utils/httpRequest.js\'
export function policy() 
   return  new Promise((resolve,reject)=>
        http(
            url: http.adornUrl("/thirdparty/oss/policy"),
            method: "get",
            params: http.adornParams()
        ).then(( data ) => 
            resolve(data);
        ).catch(err => 
            console.log("出错了...",err)
            reject(false);
        );
    );

以上是关于OSS对象存储的主要内容,如果未能解决你的问题,请参考以下文章

OSS对象存储

对象存储 OSS

OSS对象存储

阿里云oss对象存储的简单使用

阿里云对象存储OSS存储照片

阿里云对象存储OSS存储照片