侧边栏壁纸
  • 累计撰写 11 篇文章
  • 累计创建 15 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

使用阿里OSS存储文件

Pone
2022-11-10 / 0 评论 / 0 点赞 / 32 阅读 / 1,808 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-11-15,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

如何注册阿里云 以及如何使用阿里云的访问控制获取access-key 这里就不累赘了

普通上传文件

引入依赖

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

修改配置文件

spring: 
  cloud:
    alicloud:
      access-key: 你的access-key
      secret-key: 你的secret-key
      oss:
        endpoint: 地域域名

普通文件上传测试代码

@SpringBootTest
public class OSSTest{
  
  @Autowired
  private OSSClient ossClient;
  
  @Test
  void OSSTest() throws IOException {
    // 填写Bucket名称,例如examplebucket。
    String bucketName = "myBucket";
    //文件存储的路径 (非必须)
    String filePathPrefix = "pic/";
    // 待上传的文件地址
    String absolutePath = "C:\\Users\\xyzy9\\Pictures\\680BD9B4ED7B3B52593D468800D1B54F.jpg";
    // 获取文件后缀名(包含 . ) 如 .jpg
    String fileType = absolutePath.substring(absolutePath.lastIndexOf("."));
    // 使用hutool生成UUID 作为文件名
    String objectName = UUID.randomUUID().toString(true) + fileType;
    // 填写Object完整路径,包含文件名称  例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
    String ObjectPath = filePathPrefix + objectName;
    // 上传文件
    ossClient.putObject(bucketName, ObjectPath, Files.newInputStream(Paths.get(absolutePath)));
    }
}

使用这种方式上传文件 ,需要前端先将图片上传到服务器 ,然后再通过服务器上传到阿里OSS

使用签名直传

时序图

  1. 前端用户向服务端请求上传Policy
  2. 服务端向前端返回Policy
  3. 用户使用Policy将文件直接上传到阿里OSS

引入依赖

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

配置文件

spring: 
  cloud:
    alicloud:
      access-key: 你的access-key
      secret-key: 你的secret-key
      oss:
        endpoint: 地域域名
        # 上面为官方依赖所必须的配置 下面为自定义
        bucket: myBucket
        dir: "myDir/"

Controller层


/**
 * @author Pone
 * @date 2022/11/10 21:11
 */
@RestController
public class OSSController {
    @Autowired
    private OSS ossClient;
    /**
     * access-key
     */
    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;
    /**
     * 地域域名
     */
    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;
    /**
     * bucket名称
     */
    @Value("${spring.cloud.alicloud.oss.bucket}")
    private String bucket;

    /**
     * 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
     * 需要带斜杠【/】
     */
//    @Value("${spring.cloud.alicloud.oss.dir}")
//    private String dir;
  	/**
  	* 返回类型R为统一响应格式 
  	*
  	*/
    @RequestMapping("/oss/policy")
    public R policy() {
        //设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
        //此处采用日期归档
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format + "/";
        // 填写Host地址,格式为https://bucket.endpoint。
        String host = "https://" + bucket + "." + endpoint;
        // 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
        String callbackUrl = "https://192.168.0.0:8888";
        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);
    }
}

前端组件

policy.js

// 引入的http仅为向服务端发送请求的axios
import http from '@/utils/httpRequest'

export function policy () {
  return new Promise((resolve, reject) => {
    http({
      url: http.adornUrl('/thirdparty/oss/policy'),
      method: 'get',
      params: http.adornParams({})
    }).then(({data}) => {
      resolve(data)
    })
  })
}

singleUpload.vue

<template>
  <div>
    <el-upload
      action="https://bucket.endpoint"
      :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 width="100%" :src="fileList[0].url" alt="">
    </el-dialog>
  </div>
</template>
<script>
import {policy} from './policy'
import {getUUID} from '@/utils'

export default {
  name: 'singleUpload',
  props: {
    value: String
  },
  computed: {
    imageUrl () {
      return this.value
    },
    imageName () {
      if (this.value != null && this.value !== '') {
        return this.value.substr(this.value.lastIndexOf('/') + 1)
      } else {
        return null
      }
    },
    fileList () {
      return [{
        name: this.imageName,
        url: this.imageUrl
      }]
    },
    showFileList: {
      get: function () {
        return this.value !== null && this.value !== '' && this.value !== undefined
      },
      set: function (newValue) {
      }
    }
  },
  data () {
    return {
      dataObj: {
        policy: '',
        signature: '',
        key: '',
        ossaccessKeyId: '',
        dir: '',
        host: ''
        // callback:'',
      },
      dialogVisible: false
    }
  },
  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
          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)
    }
  }
}
</script>
<style>

</style>

multiUpload.vue

<template>
  <div>
    <el-upload
      action="http://https://bucket.endpoint"
      :data="dataObj"
      list-type="picture-card"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :on-remove="handleRemove"
      :on-success="handleUploadSuccess"
      :on-preview="handlePreview"
      :limit="maxCount"
      :on-exceed="handleExceed"
    >
      <i class="el-icon-plus"></i>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt/>
    </el-dialog>
  </div>
</template>
<script>
import {policy} from './policy'
import {getUUID} from '@/utils'

export default {
  name: 'multiUpload',
  props: {
    // 图片属性数组
    value: Array,
    // 最大上传图片数量
    maxCount: {
      type: Number,
      default: 30
    }
  },
  data () {
    return {
      dataObj: {
        policy: '',
        signature: '',
        key: '',
        ossaccessKeyId: '',
        dir: '',
        host: '',
        uuid: ''
      },
      dialogVisible: false,
      dialogImageUrl: null
    }
  },
  computed: {
    fileList () {
      let fileList = []
      for (let i = 0; i < this.value.length; i++) {
        fileList.push({url: this.value[i]})
      }

      return fileList
    }
  },
  mounted () {
  },
  methods: {
    emitInput (fileList) {
      let value = []
      for (let i = 0; i < fileList.length; i++) {
        value.push(fileList[i].url)
      }
      this.$emit('input', value)
    },
    handleRemove (file, fileList) {
      this.emitInput(fileList)
    },
    handlePreview (file) {
      this.dialogVisible = true
      this.dialogImageUrl = file.url
    },
    beforeUpload (file) {
      let _self = this
      return new Promise((resolve, reject) => {
        policy()
          .then(response => {
            console.log('这是什么${filename}')
            _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
            resolve(true)
          })
          .catch(err => {
            console.log('出错了...', err)
            reject(false)
          })
      })
    },
    handleUploadSuccess (res, file) {
      this.fileList.push({
        name: file.name,
        // url: this.dataObj.host + "/" + this.dataObj.dir + "/" + file.name; 替换${filename}为真正的文件名
        url: this.dataObj.host + '/' + this.dataObj.key.replace('${filename}', file.name)
      })
      this.emitInput(this.fileList)
    },
    handleExceed (files, fileList) {
      this.$message({
        message: '最多只能上传' + this.maxCount + '张图片',
        type: 'warning',
        duration: 1000
      })
    }
  }
}
</script>
<style>
</style>
  1. 如已经绑定OSS的CDN域名 可以将前端文件中action的值以及后端controller中host的值替换
  2. 如上传文件出现403错误 请在OSS后台配置跨域
0

评论区