阿里云OSS临时凭证前后端配合上传文件

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介: 阿里云OSS临时凭证前后端配合上传文件

唔姆,分享一篇企业里用的阿里云OSS临时签证直传的上传教程

项目地址…springboot+thymeleaf+jquery,简单好用,写博客、做网站专属

https://github.com/VampireAchao/ossUpload

一般的阿里云OSS上传,要么放在前端上传,暴露了accesskey和secrekey

要么放在后端,文件先传到后端,再由后端上传,让服务器压力变得巨大。。。

所以,这里一篇服务端签名后直传的教程

Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但本示例中的服务端无法实时了解用户上传了多少文件,上传了什么文件。

如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调

坏处还有就是辛苦了我们的前端同志。。。

首先开通服务

登录阿里云官网。
将鼠标移至产品,单击对象存储 OSS,打开 OSS 产品详情页面。
在 OSS 产品详情页,单击立即开通。
开通服务后,在 OSS 产品详情页单击管理控制台直接进入 OSS 管理控制台界面。
您也可以单击位于官网首页右上方菜单栏的控制台,进入阿里云管理控制台首页,然后单击左侧的对象存储 OSS 菜单进入 OSS 管理控制台界面。   //从官方文档复制的

创建一个springboot项目,勾选web和thymeleaf(导入js用到了一点)

然后导入依赖

<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: ACCESSKEY
      secret-key: SECRETKEY
      oss:
        endpoint: oss-cn-chengdu.aliyuncs.com
        bucket: waibi

然后调用,我这里用了个包装类,也一并贴上

package com.ruben.service.impl;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.ruben.common.json.AjaxJson;
import com.ruben.service.UploadService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * @ClassName: UploadServiceImpl
 * @Description: 获取OSS签证
 * @Date: 2020/6/3 21:55
 * *
 * @author: achao<achao1441470436 @ gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
@Service
public class UploadServiceImpl implements UploadService {
    @Resource
    OSS ossClient;
    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;
    @Value("${spring.cloud.alicloud.oss.bucket}")
    private String bucket;
    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;
    /**
     * 获取临时签证
     * @return
     */
    @Override
    public AjaxJson getMark() {
        String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
        // callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
//        String callbackUrl = "http://88.88.88.88:8888";
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format + "/"; // 用户上传文件时指定的前缀。
        Map<String, String> respMap = null;
        try {
            long expireTime = 3000;
            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 = 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 AjaxJson.success("获取签证成功!").put("data", respMap);
    }
}
/**
 * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
 */
package com.ruben.common.json;
import com.fasterxml.jackson.annotation.JsonIgnore;
//import com.jeeplus.core.mapper.JsonMapper;
import org.springframework.http.HttpStatus;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
 * $.ajax后需要接受的JSON
 *
 * @author
 *
 */
public class AjaxJson extends HashMap<String,Object> implements Serializable {
  public AjaxJson(){
    this.put("success", true);
    this.put("code", HttpStatus.OK.value());
    this.put("msg", "操作成功");
  }
  public String getMsg() {
    return (String)this.get("msg");
  }
  public void setMsg(String msg) {//向json中添加属性,在js中访问,请调用data.msg
    this.put("msg", msg);
  }
  public boolean isSuccess() {
    return (boolean)this.get("success");
  }
  public void setSuccess(boolean success) {
    this.put("success", success);
  }
/*  @JsonIgnore//返回对象时忽略此属性
  public String getJsonStr() {//返回json字符串数组,将访问msg和key的方式统一化,都使用data.key的方式直接访问。
    String json = JsonMapper.getInstance().toJson(this);
    return json;
  }*/
  @JsonIgnore//返回对象时忽略此属性
  public static AjaxJson success(String msg) {
    AjaxJson j = new AjaxJson();
    j.setMsg(msg);
    return j;
  }
  @JsonIgnore//返回对象时忽略此属性
  public static AjaxJson error(String msg) {
    AjaxJson j = new AjaxJson();
    j.setSuccess(false);
    j.setMsg(msg);
    return j;
  }
  public static AjaxJson success(Map<String, Object> map) {
    AjaxJson restResponse = new AjaxJson();
    restResponse.putAll(map);
    return restResponse;
  }
  public static AjaxJson success() {
    return new AjaxJson();
  }
  @Override
  public AjaxJson put(String key, Object value) {
    super.put(key, value);
    return this;
  }
  public AjaxJson putMap(Map m) {
    super.putAll(m);
    return this;
  }
  public int getCode() {
    return (int)this.get("code");
  }
  public void setCode(int code) {
    this.put("code", code);
  }
}


顺便一提,这个包装类是jeeplus的,若本教程存在任何侵权问题,请联系我删除…

controller里就很简单,就一个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.ruben.controller;
import com.ruben.common.json.AjaxJson;
import com.ruben.service.UploadService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * @ClassName: UploadController
 * @Description: 文件上传controller
 * @Date: 2020/6/3 21:53
 * *
 * @author: achao<achao1441470436 @ gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
@RestController
@RequestMapping("oss")
publicclassUploadController {
@Resource
    UploadService uploadService;
/**
     * 获取签证
     *
     * @return
     */
@GetMapping("getMark")
public AjaxJson getMark() {
return uploadService.getMark();
    }
}

然后是前端的页面,记得导入thymeleaf

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>upload</title>
    <script type="application/javascript" th:src="@{/js/upload.js}"></script>
    <script type="text/javascript" src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<input type="file" id="uploadFile" multiple="multiple">
<script>
    var firstShowImgs = true; //是否第一次调用setShowFiles()这个函数
    // uploadFile input 框回调拿到的file对象
    $('#uploadFile').change(function (e) {
        // console.log(e.target.files);
        var uploadFile=e.target.files;
        var files=[];
        for(var i=0;i<uploadFile.length;i++){ //循环push包装一下file对象
            files.push({
                returnShow: false, //当前图片是否上传完成
                url: '', //url 地址
                file: uploadFile[i], //file 对象
                isDel:false //是否删除
            })
        }
        console.log(files);
        setShowFiles(0,files);
    });
</script>
</body>
</html>

PS:前端页面是让同事帮忙写的,自己JQuery忘完了,记得导入js

const baseUrl = 'http://localhost:8080';
const utils = {
    getUUID() { //生成UUID
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
            return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
        })
    },
    getSuffix(fileName) { //获取文件后缀名
        var first = fileName.lastIndexOf(".");//取到文件名开始到最后一个点的长度
        var namelength = fileName.length;//取到文件名长度
        var filesuffix = fileName.substring(first + 1, namelength);//截取获得后缀名
        return `.${filesuffix}`
    },
    getfileName(fileName) { //获取文件名(不要后缀)
        var first = fileName.lastIndexOf(".");//取到文件名开始到最后一个点的长度
        var filesuffix = fileName.substring(0, first);//截取获得文件名
        return `${filesuffix.replace(/\s/g, "")}`
    },
    getFileUrlName(fileName) { //获取文件路径名称
        var first = fileName.lastIndexOf("/");//取到文件名开始到最后一个/的长度
        var namelength = fileName.length;//取到文件名长度
        var filesuffix = fileName.substring(first + 1, namelength);//截取获得文件名
        return `${filesuffix}`
    },
    getObjectURL(file) {  //返回文件本地路径
        var url = null;
        if (window.createObjectURL != undefined) {
            url = window.createObjectURL(file);
        } else if (window.URL != undefined) {
            url = window.URL.createObjectURL(file);
        } else if (window.webkitURL != undefined) {
            url = window.webkitURL.createObjectURL(file);
        }
        return url;
    }
}
function request(url, type, params = {}) {
    if (type == "URL_GET") {
        // console.log(params.url);
        url = url + '/' + params.url.join('/');
        delete (params['url']);
        type = 'GET';
    } else if (type == "URL_POST") {
        url = url + '/' + params.url.join('/');
        delete (params['url']);
        type = 'POST';
    }
    if (localStorage.getItem('token') && localStorage.getItem('refreshToken')) {
        params['headers'] = {//携带token
            "apiToken": localStorage.getItem('token'),
            "apiRefreshToken": localStorage.getItem('refreshToken')
        };
    }
    if (params['data'] && type == "POST") {
        params['data'] = JSON.stringify(params['data']);
    }
    return new Promise(function (resolve, reject) {
        $.ajax({
            url: baseUrl + url,
            type: type,
            ...params,
            contentType: 'application/json; charset=UTF-8',
            success: function (res) {
                if (res.code == 200) {
                    resolve(res)
                } else {
                }
            },
            error: function (res) {
                reject(res)
            }
        });
    })
}
function aliOssUploadFile(obj = {}) {
    // alert(obj);
    http.getOssInfo().then((res) => {
        if (res.code == 200 && res.success == true) {
            var config = res.data;
            var formData = new FormData();
            var filesAddress = `${config.dir}${utils.getfileName(obj.name)}-${utils.getUUID()}-${+new Date()}${utils.getSuffix(obj.name)}`;
            formData.append('key', filesAddress); //存储在oss的文件路径
            formData.append('ossaccessKeyId', config.accessid); //accessKeyId
            formData.append('policy', config.policy); //policy
            formData.append('Signature', config.signature); //签名
            formData.append("file", obj.file);
            formData.append("dir", config.dir);
            formData.append('success_action_status', 200); //成功后返回的操作码
            $.ajax({
                type: 'POST',
                data: formData,
                url: config.host,
                processData: false,
                contentType: false,
                async: true,
                xhr: function () {
                    myXhr = $.ajaxSettings.xhr();
                    if (myXhr.upload) { // check if upload property exists
                        myXhr.upload.addEventListener('progress', (e) => {
                            var loaded = e.loaded;                  //已经上传大小情况
                            var total = e.total;                      //附件总大小
                            var percent = Math.floor(100 * loaded / total) + "%";     //已经上传的百分比
                            // console.log("已经上传了:"+percent);
                            obj.success({
                                meCode: 201,
                                data: {total, loaded, percent: percent, num: Math.floor(100 * loaded / total)}
                            })
                        }, false); // for handling the progress of the upload
                    }
                    return myXhr;
                },
                success: (res) => {
                    obj.success({meCode: 200, data: {url: config.host + '/' + filesAddress}})
                },
                error: (err) => {
                    console.log(err);
                    obj.error({code: 200, success: false, msg: 'oss上传文件失败', data: err})
                }
            })
        } else {
            obj.error(res);
        }
    }).catch((err) => {
        obj.error({code: 200, success: false, msg: '获取oss签证失败', data: err});
    })
}
const http = {
    uploadFile: aliOssUploadFile, //阿里云oss上传文件
    getOssInfo: (params) => request('/oss/getMark', 'GET', params), //获取oss信息
}
// var firstShowImgs = true; //是否第一次调用setShowFiles()这个函数
// uploadFile input 框回调拿到的file对象
// for(var i=0;i<uploadFile.length;i++){ //循环push包装一下file对象
//   files.push({
//     returnShow: false, //当前图片是否上传完成
//     url: utils.getObjectURL(uploadFile[i]), //url 地址
//     file: uploadFile[i], //file 对象
//     isDel:false //是否删除
//   })
// }
// setShowFiles(0,files);
function setShowFiles(index, files) { //循环多文件上传
    if (index > files.length - 1) { //结束递归
        console.log(files);
        var arrImg = [];
        files.forEach(item => {
            if (item.returnShow == true && !item.isDel) {
                arrImg.push(item.url);
                item.isDel = true;
            }
        });
        console.log(arrImg); //结束递归时返回所有上传成功的url数组
        firstShowImgs = true; //改为初始值。
        return false
    }
    if (files[index].returnShow || files[index].isDel) {
        setShowFiles(index - 0 + 1, files); //递归下一个
        return false
    }
    http.uploadFile({ //上传
        file: files[index].file, //文件
        name: files[index].file.name, //文件名称
        success: (res) => { //成功返回
            if (res.meCode == 200) { //成功
                files[index].returnShow = true;
                files[index].url = res.data.url;
                setShowFiles(index - 0 + 1, files); //递归
            }
        },
        error: (err) => { //失败返回
            files[index].isDel = true; //,当前图片上传失败后改为删除状态就不得再次上传
            setShowFiles(index - 0 + 1, files); //递归下一个
            console.log(err);
        }
    })
}

然后把文件拖到上传按钮那里就上传了,路径拼到了控制台打印出来了

之后可以传到服务端保存到数据库里,这样就完成了保存路径的操作

相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
相关文章
|
13天前
|
分布式计算 大数据 MaxCompute
MaxCompute产品使用合集之使用pyodps读取OSS(阿里云对象存储)中的文件的步骤是什么
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
2天前
|
安全 Linux 对象存储
数据备份到阿里云oss上,以防勒索病毒的破坏
数据备份到阿里云oss上,以防勒索病毒的破坏
15 0
|
18天前
|
网络协议 对象存储
阿里云oss配置自有域名
阿里云oss配置自有域名
22 1
|
20天前
|
存储 JSON 前端开发
Javaweb之SpringBootWeb案例之阿里云OSS服务集成的详细解析
Javaweb之SpringBootWeb案例之阿里云OSS服务集成的详细解析
19 0
|
20天前
|
存储 开发工具 对象存储
Javaweb之SpringBootWeb案例之阿里云OSS服务入门的详细解析
Javaweb之SpringBootWeb案例之阿里云OSS服务入门的详细解析
19 0
|
20天前
|
存储 文字识别 安全
Javaweb之SpringBootWeb案例之阿里云OSS服务的详细解析
Javaweb之SpringBootWeb案例之阿里云OSS服务的详细解析
19 0
|
25天前
|
存储 安全 Java
全面了解阿里云OSS使用方法
本文介绍了阿里云对象存储(OSS)的准备工作、服务开通、优势、使用步骤以及代码实现。首先,用户需要注册阿里云账号并进行实名认证,然后开通OSS服务,创建存储空间。阿里云OSS提供高可靠、安全、低成本的云存储,适合各种数据存储和分发场景。接着,通过官方SDK学习如何上传文件,并提供了Java代码示例。最后,展示了如何在Spring Boot项目中集成阿里云OSS,实现文件上传功能。
|
26天前
|
存储 Java API
阿里云oss简介和使用流程
本文档介绍了如何准备阿里云OSS(对象存储服务)并开始使用它。首先,需要注册阿里云账号并进行实名认证,然后购买OSS资源包。在阿里云控制台中,可以创建和管理OSS存储空间(称为“Bucket”)。接着,文章简要介绍了阿里云OSS,它是一个基于云端的对象存储服务,提供高可靠性、高性能、低成本和易于使用的特性。 在阿里云OSS控制台,用户可以进行文件的上传和下载操作。通过API,开发者可以使用各种编程语言(如Java)来创建、删除Bucket以及上传、下载和删除文件。例如,Java代码示例展示了如何创建Bucket、上传文件、删除文件以及下载文件到本地的操作。
|
1月前
|
存储 Java API
阿里云OSS使用购买流程
本文介绍了阿里云对象存储OSS的基本使用,包括准备工作、购买开通阿里云账号并进行实名认证,以及通过Web控制台、命令行工具ossutil和SDK进行文件操作。此外,还提到了RESTful API和图形化工具OSSBrowser的使用,并给出了Java SDK下载对象的示例代码。文章内容包括了OSS的基本概念,如存储空间Bucket和对象Object,以及不同类型的存储类型。
|
1月前
|
开发工具 对象存储
阿里云OSS文件上传
阿里云OSS文件上传
74 0

热门文章

最新文章