浏览器Web、小程序前端等直接上传图片文件到阿里云OSS(springboot版完整代码)

作者: ʘᴗʘ发布时间:2021-11-27 19:28 浏览量:450 点赞:337 售价:0

简介

前文我们介绍了上传图片文件到阿里云的两种方案:

  1. 传统方式上传,通过web表单、小程序上传组件等,先把图片传到业务服务器,然后业务服务器再把图片转存到OSS。
  2. 前端先从业务服务器拿一个上传凭证,然后带着这个凭证直接把图片上传到阿里云OSS。

第一种方案我们在Springboot上传图片到阿里云OSS新手教程(完整代码)中有详细介绍,需要的朋友可以阅读参考一下。本文重点介绍第二种方案:WEB前端直传图片到阿里云OSS。

Web直传参数介绍

逻辑描述:和传统的web表单上传一样,web直传也是通过post请求上传文件。区别是web直传的post请求,请求body中除了文件外,还需要携带一些其他阿里云OSS的验证参数。一句话描述,就是传统表单的上传的POST请求,在body内再增加一些参数,就可以web直传了。

具体参数如下:

  • key:文件的路径+名称信息。比如你要把1.jpg上传到阿里云OSS的data/test/666/目录,那么这个key就是data/test/666/1.jpg。
  • policy:上传策略。可以理解为上传的配置信息,比如文件的存放位置、该上传凭证的有效时间等等。
  • OSSAccessKeyId:阿里云账号的AccessKey,这个就不做介绍了,直接在阿里云后台复制过来就行。
  • signature:签名信息。根据一定的规则和信息生成的签名信息,保证只有你自己才可以往你的阿里云OSS上传东西。签名计算方法为Signature = base64(hmac-sha1(base64(policy), AccessKeySecret))。后面会有代码演示签名。
  • callback:回调信息。就是当前端上传图片文件到阿里云OSS后,如果这里回调信息不为空,那么阿里云OSS会再发一起一个HTTP请求,请求你callback里配置的这个地址,并携带一些参数。可以理解为上传成功后,让阿里云OSS发起一个请求通知你的服务器。回调里可以携带诸如图片大小、格式、尺寸等等信息。

完整上传代码

因为前端有很多很多种,如果你是微信小程序,你可以通过HTTP请求来从自己的业务服务器获取上传凭证;如果你是VUE的网页,也可以通过AXIOS等ajax库来获取上传凭证;如果你是使用Vue+ElementUI这种方式,那么只要在el-upload组件里,通过before-upload提前请求业务服务器,拿到上传凭证即可。

为了照顾大家使用的不同前端技术,我这里用最传统的表单来演示,你使用的时候,根据你自己使用的前端技术,稍作改动即可。

springboot图片上传controller代码

下面代码中,主要是两个请求:

  • 第一个请求是返回上传网页的,使用的thymeleaf模板引擎。
  • 第二个请求是一个ajax API接口,前端客户端请求这个API,就能拿到上传阿里云OSS所需的凭证了。

代码如下:

package com.coderbbb.book1.controller;

import com.coderbbb.book1.database.dto.JsUploadDTO;
import com.coderbbb.book1.service.AliyunOssService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UploadController2 {

    @Autowired
    private AliyunOssService aliyunOssService;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @RequestMapping(value = "/upload/webPage2", method = RequestMethod.GET)
    public String webPage() {
        return "webPage2";
    }

    @RequestMapping(value = "/upload/webPage2/api", method = RequestMethod.GET)
    @ResponseBody
    public JsUploadDTO webPost() {
        try {
            return aliyunOssService.jsUploadFile("data/", "ttt.jpg", 100 * 1024 * 1024, null);
        } catch (Exception e) {
            logger.error("upload err",e);
        }
        return null;
    }
}

springboot直接上传阿里云OSS凭证代码

上面的controller代码中,使用了一个名为AliyunOssService的service,这个service里封装了构造web直传所需数据的方法,代码如下:

package com.coderbbb.book1.service;

import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.ResponseMessage;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.*;
import com.coderbbb.book1.database.dto.JsUploadDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * @Author: longge93
 * @Date: 2021/6/10 13:32
 */
@Service
public class AliyunOssService {

    private final String ACCESS_KEY = "access key";

    private final String SECRET_KEY = "secret key";

    private final String ENDPOINT = "oss-accelerate.aliyuncs.com";

    private final String BUCKET = "66tec-ap";

    private static OSSClient ossClient;

    private synchronized void createOssClient() {
        if (ossClient == null) {
            DefaultCredentialProvider defaultCredentialProvider = new DefaultCredentialProvider(ACCESS_KEY, SECRET_KEY);
            ClientConfiguration config = null;
            ossClient = new OSSClient(ENDPOINT, defaultCredentialProvider, config);
        }
    }

    private OSSClient getOssClient() {
        if (ossClient == null) {
            createOssClient();
        }
        return ossClient;
    }



    public String uploadInputStreamFile(String key, InputStream inputStream, CannedAccessControlList acl, Callback callback) throws Exception {

        PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET, key, inputStream);
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setObjectAcl(acl);
        putObjectRequest.setMetadata(metadata);

        if (callback != null) {
            putObjectRequest.setCallback(callback);
        }

        PutObjectResult putObjectResult = getOssClient().putObject(putObjectRequest);
        ResponseMessage responseMessage = putObjectResult.getResponse();
        if (responseMessage != null && callback != null) {
            InputStream content = responseMessage.getContent();
            String result = new String(content.readAllBytes());
            content.close();
            return result;
        }
        return null;
    }


    /**
     * 传入上传基本路径和文件名,返回JS直传所需的加密信息和签名
     *
     * @param basePath
     * @param fileName
     * @param uploadCallbackStr 回调
     * @return
     * @throws Exception
     */
    public JsUploadDTO jsUploadFile(String basePath, String fileName, long maxSize, String uploadCallbackStr) throws Exception {


        //上传文件签名信息过期时间
        long UPLOAD_EXPIRE_TIME = 60 * 5 * 1000;
        Date expireTime = new Date(System.currentTimeMillis() + UPLOAD_EXPIRE_TIME);

        PolicyConditions policyConds = new PolicyConditions();

        //文件大小
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
        //文件路径限制
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, basePath);

        String postPolicy = getOssClient().generatePostPolicy(expireTime, policyConds);
        byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);

        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = getOssClient().calculatePostSignature(postPolicy);

        JsUploadDTO jsUploadDTO = new JsUploadDTO();
        jsUploadDTO.setAccessId(ACCESS_KEY);
        jsUploadDTO.setExpireTime(expireTime);
        jsUploadDTO.setHost(BUCKET + "." + ENDPOINT);
        jsUploadDTO.setPath(basePath + fileName);
        jsUploadDTO.setPolicy(encodedPolicy);
        jsUploadDTO.setSignature(postSignature);

        if (StringUtils.isNotEmpty(uploadCallbackStr)) {
            jsUploadDTO.setCallBack(uploadCallbackStr);
        }

        return jsUploadDTO;
    }

}

其中,uploadInputStreamFile函数是上一篇文章中,通过业务服务器上传OSS的代码,你用不到可以删掉。

springboot所需阿里云OSS SDK

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

HTML前端网页代码

这部分代码就是传统的表单上传,为了更像Vue、微信小程序等上传的样子,我用Jquery实现了上传。主要分两步:

  • 第一步使用Jquery的Ajax请求服务器,拿到上传凭证。
  • 第二步使用Jquery的Ajax直接构造一个HTML Form表单,把文件File数据、上传凭证数据等,一起传给阿里云OSS,完成上传。

PS:这里有一个点需要注意,就是你在构造上传表单的时候,务必把文件File这一项放到整个表单数据最后,否则阿里云OSS会报错。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传图片</title>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>


<div>
    <form action="" name="upload" method="post" enctype="multipart/form-data">

        <input type="file" id="file" name="file">

        <button type="button" id="beginUpload">点击开始上传</button>
    </form>
</div>

<script>
    $(function () {
        $("#beginUpload").on("click",function () {
            $.ajax({
                url:'/upload/webPage2/api',
                type:'get',
                success:function(res){

                    //已经获取到上传所需的凭证数据
                    let uploadBaseData = res;

                    //开始构造上传表单数据,准备上传
                    let formData = new FormData();

                    formData.append("key",uploadBaseData.path);
                    formData.append("policy",uploadBaseData.policy);
                    formData.append("OSSAccessKeyId",uploadBaseData.accessId);
                    formData.append("signature",uploadBaseData.signature);
                    formData.append("file",$("#file")[0].files[0]);

                    //开始上传图片到阿里云OSS
                    $.ajax({
                        url:'http://' + uploadBaseData.host,
                        type:'post',
                        data: formData,
                        contentType: false,
                        processData: false,
                        success:function(res){
                            console.log(res);
                        }
                    })
                }
            })
        });
    });
</script>

</body>
</html>

效果演示

上传HTML界面(有点简陋,见谅~)

浏览器Web、小程序前端等直接上传图片文件到阿里云OSS(springboot版完整代码)

上传成功后,到阿里云OSS后台查看文件:

浏览器Web、小程序前端等直接上传图片文件到阿里云OSS(springboot版完整代码)

版权声明:《浏览器Web、小程序前端等直接上传图片文件到阿里云OSS(springboot版完整代码)》为CoderBBB作者「ʘᴗʘ」的原创文章,转载请附上原文出处链接及本声明。

原文链接:https://www.coderbbb.com/articles/44

其它推荐: