阿里OSS 上传图片 springboot整合阿里云OSS做服务端签名让微信小程序文件直传OSS

前段web参考地址:https://www.cnblogs.com/pnz-bug/p/10381839.html

后台java 才考地址:https://blog.csdn.net/huangxiangdi/article/details/104725048/

1、需求:

想让小程序直接上传图片、文件到OSS存储,不需要经过我的服务器接收文件再转发到OSS存储。

好处

  • 可以减轻自己服务器的压力,和不必要的麻烦。

  • 有利于维护和扩展(比如扩容、迁移等等)。

  • 可以更加快的存储到OSS中,不需要多次来回传输。

  • 不占用自己服务器的带宽,阿里的OSS节点处理更快。

  • 等等。。。

2、基本原理介绍(官方描述,我觉得很简单了)

在这里插入图片描述

服务端签名后前端(小程序)直传的原理如下:

  1. 用户发送请求到自己服务器获取上传的Policy和签名。
  2. 自己的服务器返回前端直传oss需要Policy和签名给用户。
  3. 用户直接上传数据到OSS。

3、springboot 搞起来

1.新建一个springboot 项目,添加依赖

<!--阿里oss-->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.8.3</version>
</dependency>

2.编写一个OSS的配置类(可以根据自己的需求来,注入等方式都可以)

public class AliOssConfig {
    /**
     * 填写您的AccessKeyId
     */
    public final static String accessId = "xxxx";
    /**
     * 填写您的AccessKeySecret
     */
    public final static String accessKey = "xxxxx";
    /**
     * 填写您的 endpoint(地域节点),就是你OSS的区域节点的域名
     */
    public final static String endpoint = "xxxx.aliyuncs.com";
    /**
     * 填写您的 bucketName ,就是你再OSS创建Bucket的名称
     */
    public final static String bucket = "xxx";
    /**
     * 直传地址,格式为 bucketName.endpoint (Bucket域名)
     */
    public final static String host = "https://" + bucket +"."+ endpoint;

    /*
     * ============= 配置上传过期时间、大小等等 =========
     */
    /**
     * 上传截止时间(秒)
     */
    public final static long expireTime = 30;

    /**
     * 上传文件最小(字节)
     */
    public final static long min = 0;
    /**
     * 上传文件最大(字节)
     */
    public final static long max = 1048576000;

    /**
     * 上传文件的前缀、可忽略
     */
    public final static String dir = "user/";
}

3.创建controller

@RestController
@RequestMapping("/ali/oss")
public class AliOssController {
    /**
     * 创建OSS客户端
     */
    private OSSClient client = new OSSClient(AliOssConfig.endpoint, AliOssConfig.accessId, AliOssConfig.accessKey);

    /**
     * 前端获取直传的policy信息
     * 前端可以使用响应的参数进行直传到oss存储
     *
     * @return
     */
    @GetMapping("/policy")
    public AliOssPolicy getPolicy() {
        // 直传有效截止时间
        long expireEndTime = System.currentTimeMillis() + (AliOssConfig.expireTime * 1000);
        Date expiration = new Date(expireEndTime);
        PolicyConditions policyConditions = new PolicyConditions();
        // 设置可上传文件的大小
        policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, AliOssConfig.min, AliOssConfig.max);
        // 设置上传文件的前缀、可忽略
        policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, AliOssConfig.dir);
        // 生成policy
        String postPolicy = client.generatePostPolicy(expiration, policyConditions);
        byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = client.calculatePostSignature(postPolicy);
        // 封装policy等信息
        AliOssPolicy aliOssPolicy = new AliOssPolicy();
        aliOssPolicy.setOssAccessKeyId(AliOssConfig.accessId);
        aliOssPolicy.setPolicy(encodedPolicy);
        aliOssPolicy.setSignature(postSignature);
        aliOssPolicy.setDir(AliOssConfig.dir);
        aliOssPolicy.setHost(AliOssConfig.host);
        aliOssPolicy.setExpire(String.valueOf(expireEndTime / 1000));
        return aliOssPolicy;
    }
}

4.创建一个封装类来响应给前端

public class AliOssPolicy implements Serializable {
    /**
     * 上传认证id
     */
    private String ossAccessKeyId;
    /**
     * policy
     */
    private String policy;
    /**
     * 签名
     */
    private String signature;
    /**
     * 直传文件的开头(路径)
     */
    private String dir;
    /**
     * 直传地址
     */
    private String host;
    /**
     * 上传截止时间
     */
    private String expire;
	
    // get和set省略
}

5、小程序 搞起来

// 调用小程序api选择图片上传
    wx.chooseImage({
      success: function(res) {
        var tempFilePaths = res.tempFilePaths
        // 上传图片到oss
        wx.uploadFile({
          // 直传的oss地址
          url: 'https://xxxx.xxxx.aliyuncs.com',
          // 上传的文件
          filePath: tempFilePaths[0],
          // 必须为file
          name: 'file',
          // 表单数据
          formData: {
            // key:文件路径,如 user/666.png
            //直接 key: "${filename}" 是存放在根目录,文件名为上传的文件名
            // 如果后端签名时指定了dir则开头必须同后端的一致,如后端指定了 “user/” 开头则必须是 user/xxx.xx
            key: "user/666.png",
            // 自定义成功响应值 ,默认响应204
            success_action_status: '200',
            OssAccessKeyId: 'xxxx',
            // 后端签名后发回的policy
            policy: 'xxxxxx',
            // 后端返回的签名
            signature: 'xxxxx'
          },
          success: function(res) {
            if (res.statusCode == 200) {
              console.log("上传成功!")
              console.log(res)
            } else {
              console.log("上传失败!")
              console.log(res)
            }
          },
          fail(error) {
            console.log("上传错误")
            console.log(error)
          }
        })
      }
    })

 1.设置跨域问题请参考阿里OSS 文件

 

前段javascript例子: web OSS 阿里上传 参考地址:

https://www.cnblogs.com/pnz-bug/p/10381839.html

<!-- 项目源码地址  https://github.com/Pangnz/OssUpload --><br><!DOCTYPE html>

<html>

    <head>

        <meta charset="utf-8" />

        <title>web直传oss</title>

        <style type="text/css">

            .file-box {

                position: relative;

                display: inline-block;

                width: 160px;

                height: 160px;

                background: url(img/aaa.png) no-repeat;

                background-size: cover;

                background-position: center;

            }

 

            #input_file {

                width: 100%;

                height: 100%;

                opacity: 0;

                filter: alpha(opacity=0);

            }

        </style>

    </head>

 

    <body>

        <p>oss web服务端签名后直传</p>

        <div class="file-box">

            <input type="file" value="" name="file" id="input_file" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"

             onchange="imgPreview(this,0)">

        </div>

        <script src="js/jquery-3.3.1.min.js" type="text/javascript" charset="utf-8"></script>

        <script type="text/javascript">

            let uploadObj; // 上传凭证对象

            let verifyImg; //上传之后的图片oss地址

            function imgPreview(fileDom, i) {

                // 获取上传凭证

                $.ajax({

                    url: '', // 这里是请求的后台通过oss上传凭证的接口

                    data: JSON.stringify({

                        data: ''

                    }),

                    dataType: 'json',

                    type: 'post',

                    headers: {

                        'Content-Type': 'application/json',

                    },

                    success: function(response) {

                        if (response && response.header.ret == 'S') {

                            uploadObj = response.data;

                            // 获取到上传凭证成功之后 封装请求的数据

                            let request = new FormData();

                            request.append("OSSAccessKeyId", uploadObj.accessid); //Bucket 拥有者的Access Key Id。

                            request.append("policy", uploadObj.policy); //policy规定了请求的表单域的合法性

                            request.append("Signature", uploadObj.signature); //根据Access Key Secret和policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性

                            //---以上都是阿里的认证策略                           

                            let file = document.getElementById("input_file").files[0];

                            if (!file) {

                                return;

                            }

                            request.append("key", `${uploadObj.dir}/${file.name}`); //文件名字,可设置路径

                            request.append("success_action_status", '200'); // 让服务端返回200,不然,默认会返回204

                            request.append('file', file); //需要上传的文件 file 

                            $.ajax({

                                url: uploadObj.host, //上传阿里地址

                                data: request,

                                processData: false, //默认true,设置为 false,不需要进行序列化处理

                                cache: false, //设置为false将不会从浏览器缓存中加载请求信息

                                async: false, //发送同步请求

                                contentType: false, //避免服务器不能正常解析文件---------具体的可以查下这些参数的含义

                                dataType: 'json', //不涉及跨域  写json即可

                                type: 'post',

                                success: function(response) { //callbackHost:success,request中就是 回调的一些信息,包括状态码什么的

                                    // console.log(response);

                                },

                                error: function(error) {

                                    alert("上传图片成功");

                                    verifyImg = `${uploadObj.host}/${uploadObj.dir}/${file.name}`;

                                }

                            });

                        } else {

                            alert(`${response && response.header.msg[0]}`);

                        }

                    },

                    error: function(error) {

                        console.log(error);

                    },

                });

                console.log(`上传的文件oss地址${verifyImg}`);

                //判断是否支持FileReader

                if (window.FileReader) {

                    var reader = new FileReader();

                } else {

                    alert("您的设备不支持图片预览功能,如需该功能请升级您的设备!");

                }

                //获取文件

                var file = fileDom.files[0];

                if (!file) {

                    return;

                }

                var imageType = /^image\//;

                //是否是图片

                if (!imageType.test(file.type)) {

                    alert("请选择图片!");

                    return;

                }

                //读取完成

                reader.onload = function(e) {

                    //图片路径设置为读取的图片

                    // img.src = e.target.result;

                    document.getElementsByClassName('file-box')[i].style.background = "url(" + e.target.result + ")no-repeat"; //回显图片

                    document.getElementsByClassName('file-box')[i].style.backgroundSize = '';

                };

                reader.readAsDataURL(file);

            }

        </script>

    </body>

</html>

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值