阿里云OSS上传图片

一、OSS(对象存储服务)

1、介绍

对象存储服务:阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
OSS官方介绍地址:https://help.aliyun.com/document_detail/31947.html
使用前提:必须开通OSS服务

在这里插入图片描述

二、使用OSS上传图片

1、引入Maven依赖

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

2、配置yml

server:
  port: 9999

spring:
  application:
    name: marketing-third

# oss相关配置,需要在阿里云上获取
oss:
  accessId: LTAI4G2PSmNiCPnqaTdc5JUS
  accessKey: OVmknks3UYf3nKz4dougCrRK6K76NX
  bucketName: marketing-shop
  endPointKey: oss-cn-beijing.aliyuncs.com
  url: https://marketing-shop.oss-cn-beijing.aliyuncs.com

3、启动类

@SpringBootApplication
public class MarketingThirdApplication {

    public static void main(String[] args) {
        SpringApplication.run(MarketingThirdApplication.class, args);
    }

}

4、config配置类

package com.itan.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @Date: 2020/12/15
 * oss图片上传服务配置
 */
@ConfigurationProperties(prefix = "oss")
@Component
@Data
public class OssConfig {
    private String accessId;

    private String accessKey;

    private String bucketName;

    private String endPointKey;

    private String url;
}

5、文件上传工具类

1、流式文件上传
2、web直传获取签名后上传
package com.itan.config;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.PolicyConditions;
import java.io.InputStream;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Date: 2020/12/15
 * 阿里oss
 */
public class AliOss {
    private OSS ossClient;
    private String bucketName;

    public AliOss(String accessId, String accessKey, String bucketName, String endPoint) {
        this.bucketName = bucketName;
        //创建ossClient实例
        this.ossClient = new OSSClientBuilder().build(endPoint, accessId, accessKey);
        this.ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicReadWrite);
    }

    /**
     * 文件上传流
     * @param fileName
     * @param inputStream
     */
    public void uploadFileInputStream(String fileName, InputStream inputStream) {
        try {
            this.ossClient.putObject(this.bucketName, fileName, inputStream);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //关闭ossClient
            this.ossClient.shutdown();
        }
    }

    /**
     * web直传获取签名
     * @param expiration
     * @param policyConds
     * @return
     */
    public Map<String,String> getEncodedPolicyAndSignature(Date expiration, PolicyConditions policyConds) {
        Map<String,String> map = new LinkedHashMap<String, String>();
        try {
            //根据到期时间生成policy策略
            String policy = ossClient.generatePostPolicy(expiration, policyConds);
            //对policy进行UTF-8编码后转base64
            byte[] bytes = policy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(bytes);
            //生成签名,policy表单域作为填入的值,将该值作为将要签名的字符串
            String postSignature = ossClient.calculatePostSignature(policy);
            map.put("encodedPolicy",encodedPolicy);
            map.put("postSignature",postSignature);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
        }
        return map;
    }
}

6、业务接口类

package com.itan.service;

import org.springframework.web.multipart.MultipartFile;
import java.util.Map;

/**
 * @Date: 2020/12/15
 */
public interface AliOssService {
    /**
     * 上传文件到oss
     * @param file
     * @return
     */
    String uploadFile(MultipartFile file);

    /**
     * web直传获取签名
     * @return
     */
    Map<String, String> policy();
}
package com.itan.service.impl;

import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.itan.config.AliOss;
import com.itan.config.OssConfig;
import com.itan.service.AliOssService;
import com.itan.utils.BusinessException;
import com.itan.utils.ResultCodeAndMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * @Date: 2020/12/15
 */
@Slf4j
@Service
public class AliOssServiceImpl implements AliOssService {
    @Autowired
    private OssConfig ossConfig;

    /**
     * 上传文件到oss
     * @param file
     * @return
     */
    @Override
    public String uploadFile(MultipartFile file) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (null == file || file.isEmpty()) {
            throw new BusinessException(ResultCodeAndMessage.build(ResultCodeAndMessage.BUSINESS_ERROR, "上传文件不能为空"));
        }
        //获取文件名
        String originalFilename = file.getOriginalFilename();
        //生成上传文件名(当前时间字符串+文件名后缀)
        String fileName = System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf("."));
        //同一天上传的文件存放一个文件夹
        String objName = sdf.format(new Date()) + "/" + fileName;
        try {
            AliOss aliOss = new AliOss(ossConfig.getAccessId(), ossConfig.getAccessKey(), ossConfig.getBucketName(), ossConfig.getEndPointKey());
            aliOss.uploadFileInputStream(objName, file.getInputStream());
        } catch (IOException e) {
            throw new BusinessException(ResultCodeAndMessage.build(ResultCodeAndMessage.BUSINESS_ERROR, "上传文件阿里云服务异常"));
        }
        return ossConfig.getUrl() + objName;
    }

    /**
     * web直传获取签名
     * @return
     */
    @Override
    public Map<String, String> policy() {
        //用户上传文件时指定的前缀(格式:2020-12-17/)
        String dir = new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "/";
        // 创建AliOss实例
        AliOss aliOss = new AliOss(ossConfig.getAccessId(), ossConfig.getAccessKey(), ossConfig.getBucketName(), ossConfig.getEndPointKey());
        //设置签名有效期30s
        long expireTime = 30;
        long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
        Date expiration = new Date(expireEndTime);
        //PostObject请求最大可支持的文件大小为5GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024
        PolicyConditions policyConds = new PolicyConditions();
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
        //指定此次上传的文件名必须是dir变量的值开头
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
        Map<String, String> map = aliOss.getEncodedPolicyAndSignature(expiration, policyConds);
        map.put("accessId",ossConfig.getAccessId());
        //上传目录
        map.put("dir", dir);
        //地址
        map.put("host", ossConfig.getUrl());
        //过期时间
        map.put("expire", String.valueOf(expireEndTime / 1000));
        return map;
    }
}

7、controller类

package com.itan.controller;

import com.alibaba.fastjson.JSON;
import com.itan.service.AliOssService;
import com.itan.utils.BusinessException;
import com.itan.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * @Date: 2020/12/15
 */
@Slf4j
@RestController
@RequestMapping("oss")
public class AliOssController {
    @Autowired
    private AliOssService aliOssService;

    /**
     * 流式上传文件
     * @param imageFile
     * @return
     */
    @PostMapping("upload")
    public CommonResult upload(MultipartFile imageFile){
        CommonResult result;
        try {
            result = CommonResult.successResult(aliOssService.uploadFile(imageFile));
        } catch (BusinessException te) {
            log.error(te.getErrorMessage(), te);
            result = CommonResult.createResult(te.getResultCodeAndMessage());
        }
        log.info("上传文件到oss - 出参:{}", JSON.toJSONString(result));
        return result;
    }

    /**
     * web直传获取签名的原理如下:
     * 1、用户发送上传Policy请求到应用服务器。
     * 2、应用服务器返回上传Policy和签名给用户。
     * 3、用户直接上传数据到OSS。
     * @return
     */
    @RequestMapping("policy")
    public CommonResult policy(){
        CommonResult result;
        try {
            result = CommonResult.successResult(aliOssService.policy());
        } catch (BusinessException te) {
            log.error(te.getErrorMessage(), te);
            result = CommonResult.createResult(te.getResultCodeAndMessage());
        }
        log.info("web直传获取签名 - 出参:{}", JSON.toJSONString(result));
        return result;
    }
}

8、阿里云OSS配置跨域

在这里插入图片描述

9、启动测试

接口地址:http://localhost:9999/oss/policy
返回参数:
{
    "msg": {
        "code": "20000",
        "message": "请求成功"
    },
    "data": {
        "encodedPolicy": "eyJleHBpcmF0aW9uIjoiMjAyMC0xMi0zMFQwODowMjowNC5zOTFaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIyMDIwLTEyLTMwLyJdXX0=",
        "postSignature": "dEhfbmObhsp85c7xIXu0kY6oOC0=",
        "accessId": "LTAI4G2PSmNiCPnqaTdc5JUS",
        "dir": "2020-12-30/",
        "host": "https://marketing-shop.oss-cn-beijing.aliyuncs.com/",
        "expire": "1609315324"
    },
    "success": true
}

10、前端上传代码

获取签名
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);
        })
    });
}
上传组件
<template> 
  <div>
    <el-upload
      action="http://marketing-shop.oss-cn-beijing.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 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.encodedPolicy;
            _self.dataObj.signature = response.data.postSignature;
            _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("赋值后数据:",this.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);
      }
    }
  }
</script>
<style>
</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值