vue+oss实现服务端签名后直传的图片上传功能

news2025/1/17 21:32:29

vue+oss实现服务端签名后直传的图片上传功能


vue+oss实现服务端签名后直传的图片上传功能

  • vue+oss实现服务端签名后直传的图片上传功能
  • 前言
  • 一、java服务端签名接口设计
  • 二、Vue + element UI的upload图片上传
  • 三、前端直传oss可能出现跨域问题
  • 四、服务端签名流程
  • 总结


前言

基于Post Policy的使用规则在服务端通过java后端代码完成签名,然后通过表单直传数据到OSS。由于服务端签名直传无需将AccessKey暴露在前端页面,相比JavaScript客户端签名直传具有更高的安全性。


一、java服务端签名接口设计

  1. 引入OSS依赖
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
  1. Controller层设计
    @GetMapping("/policy")
    public R policy() {
        LinkedHashMap<String, String> map = ossService.policy();
        return R.ok().put("data",map);
    }
  1. 实现类设计
@Autowired
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;

public LinkedHashMap<String, String> policy() {

        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        // 填写Host地址,格式为https://bucketname.endpoint。
        String host = "https://" + bucket + "." + endpoint;
        // 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
//        String callbackUrl = "https://192.168.0.0:8888";
        // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
        String dir = "banner/uat/";

        Map<String, String> respMap = null;
        // 创建ossClient实例。
//        OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
        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 = 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));
            // 设置服务端返回200状态码,默认返回204。
            respMap.put("success_action_status","200");
        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        }
        return (LinkedHashMap<String, String>) respMap;
    }

在这里插入图片描述

二、Vue + element UI的upload图片上传

  1. 页面
    在这里插入图片描述
  2. 图片上传前处理方法
    在这里插入图片描述
  3. 上传成功后调用方法
    在这里插入图片描述
  4. 前端完整代码
    父组件:
<el-form-item label="上传图片" :prop="image" :rules="rules.image">
   <SingleUpload v-model="image"></SingleUpload>
 </el-form-item>
import SingleUpload from "@/views/subupload";

子组件:

<template>
  <div>
    <el-upload
      class="avatar-uploader"
      :data="dataObj"
      action="https://ron-test.oss-cn-shanghai.aliyuncs.com"
      :show-file-list="false"
      :on-success="handleAvatarSuccess"
      :before-upload="beforeAvatarUpload"
    >
      <img v-if="imageUrl" :src="imageUrl" class="avatar" />
      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
    </el-upload>
  </div>
</template>

<script>
import { policy } from "@/api/upload";
export default {
  name: "singleUpload",
  props: {
    value: String
  },
  computed: {
    imageUrl() {
      return this.value;
    }
  },
  data() {
    return {
      //   imageUrl: "",
      dataObj: {
        accessId: "",
        policy: "",
        signature: "",
        dir: "",
        host: "",
        expire: ""
      }
    };
  },
  methods: {
    emitInput(val) {
      this.$emit("input", val);
    },
    handleAvatarSuccess(file) {
      console.log("上传成功", file);
      //   this.imageUrl = URL.createObjectURL(file.raw);
      this.emitInput(
      	// 将图片路径传给父组件
        this.dataObj.host + "/" + this.dataObj.key.replace("${filename}", file.name)
      );
    },
    beforeAvatarUpload(file) {
      console.log(file);
      let _self = this;
      return policy()
        .then(response => {
          console.log("响应的数据", response.data);
          _self.dataObj.policy = response.data.policy;
          _self.dataObj.signature = response.data.signature;
          _self.dataObj.ossaccessKeyId = response.data.accessId;
          _self.dataObj.key = response.data.dir + "random" + file.name;
          _self.dataObj.dir = response.data.dir;
          _self.dataObj.host = response.data.host;
          // 设置服务端返回200状态码,默认返回204。
          _self.dataObj.success_action_status = response.data.success_action_status;
          console.log("响应的数据222。。。", _self.dataObj);
        })
        .catch(err => {
          console.log("error", err);
        });
    }
  },
  created() {},
  mounted() {}
};
</script>

<style>
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
.bg-purple {
  background: #d3dce6;
}
.bg-purple-light {
  background: #e5e9f2;
}
.grid-content {
  border-radius: 4px;
  min-height: 36px;
}
</style>

在这里插入图片描述

三、前端直传oss可能出现跨域问题

需要进入oss修改相关跨域策略
在这里插入图片描述
编辑跨域规则
在这里插入图片描述
确定保存
在这里插入图片描述

四、服务端签名流程

在这里插入图片描述

  1. 用户向应用服务器请求上传Policy和回调
  2. 应用服务器返回上传Policy和签名给用户
    在这里插入图片描述
字段描述
accessId用户请求的AccessKey ID
policy用户表单上传的策略(Policy),Policy为经过Base64编码过的字符串
signature对Policy签名后的字符串
dir限制上传的文件前缀
host用户发送上传请求的域名 说明:host不支持自定义域名
expire由服务器端指定的Policy过期时间,格式为Unix时间戳(自UTC时间1970年01月01号开始的秒数)
  1. 用户使用Post方法向OSS发送文件上传请求
    在这里插入图片描述

总结

与数据上传至服务器,再由服务器上传到oss相比:(Vue+element Upload利用http-request实现第三方地址图片上传)

  • 上传快:通过应用服务端上传,用户数据需先上传到应用服务器,之后再上传到OSS,网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
  • 扩展性好:如果后续用户数量逐渐增加,则应用服务器会成为瓶颈。
  • 费用低:由于OSS上行流量是免费的,如果数据直传到OSS,将节省多台应用服务器的费用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/443429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java基层卫生健康云源码 医院HIS信息管理系统源码

近年来&#xff0c;随着互联网技术的快速发展&#xff0c;云计算技术也得到了广泛的应用。云计算技术不仅可以提高计算效率&#xff0c;还可以实现资源的共享和协同&#xff0c;为基层卫生健康事业的发展提供了新的思路和机遇。 基层卫生健康云系统是指利用云计算技术&#xf…

【Java|golang】1026. 节点与其祖先之间的最大差值---避坑,注意:golang中同一个包下的全局变量只加载一次。

给定二叉树的根节点 root&#xff0c;找出存在于 不同 节点 A 和 B 之间的最大值 V&#xff0c;其中 V |A.val - B.val|&#xff0c;且 A 是 B 的祖先。 &#xff08;如果 A 的任何子节点之一为 B&#xff0c;或者 A 的任何子节点是 B 的祖先&#xff0c;那么我们认为 A 是 B…

环境变量的初始

目录 &#xff1a; 1.引出环境变量 2. 简单使用一下环境变量 3.环境变量的概念 4.本地变量 5.环境变量的相关命令 6.环境变量获取和操作的方式 7. getenv&#xff08;最常用的程序获取环境变量的方式&#xff09; 8.环境变量的全局属性 -------------------------------------…

擎创动态 | 二等奖!擎创携手国家电网喜获“浪潮信息杯”绝佳成绩

近日&#xff0c;2022电力行业信息化年会于湖南省长沙市圆满落下帷幕。据悉&#xff0c;今年是电力行业信息化年会举办的第二十周年&#xff0c;年会的主题为“低碳数字新动力 电力转型新发展”&#xff0c;紧密围绕“十四五”数据经济发展&#xff0c;“双碳”战略、新型电力系…

10分钟学会使用Jmeter工具做接口自动化测试

Jmeter接口自动化测试项目实战视频教程地址&#xff1a;https://www.bilibili.com/video/BV1e44y1X78S/? 目录&#xff1a;导读 引言 一、软件下载 二、软件安装及设置环境变量 三、Jmeter做接口自动化测试的步骤 四、接口依赖的解决 引言 大家好&#xff01;我是不二。…

《Linux基础》08. 日志管理 · 备份与恢复

Linux基础 - 08 1&#xff1a;日志管理1.1&#xff1a;系统常用日志1.2&#xff1a;日志管理1.2.1&#xff1a;日志服务1.2.2&#xff1a;配置文件1.2.3&#xff1a;自定义日志管理 1.3&#xff1a;日志轮替1.3.1&#xff1a;轮替服务1.3.2&#xff1a;配置文件1.3.3&#xff1…

顺序表(更新版)——“数据结构与算法”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰又来更新新专栏啦&#xff0c;其实之前我就已经写过了顺序表的内容&#xff0c;只是之前的内容不是最新版的顺序表&#xff0c;现在&#xff0c;我来更新一下最新版的顺序表&#xff0c;下面&#xff0c;就让我们进入更新版的顺序…

开发常用的 Linux 命令1(文件和目录)

开发常用的 Linux 命令汇总1&#xff08;文件和目录&#xff09; 作为开发者&#xff0c;Linux是我们必须掌握的操作系统之一。因此&#xff0c;在编写代码和部署应用程序时&#xff0c;熟练使用Linux命令非常重要。这些常用命令不得不会&#xff0c;掌握这些命令&#xff0c;…

小项目发布:TLC_Browers--一个开源的基于vb6基于Webview2 Runtime支持html5和多标签的浏览器

项目名称:TLC浏览器(TLC_NLP机器人的附属产品) 技术架构:webview2 runtime,可参考链接WebView2 - Microsoft Edge Developer 目录介绍: kernel:控制webview2内核的代码 client:主程序代码&#xff0c;将kernel变为自己的子窗体&#xff0c; 进程通信方式:共享文件 release:正…

Jenkins 在linux安装配置

下载Jenkins 安装包 官网地址&#xff1a;https://www.jenkins.io/index.html 因为我的是centos&#xff0c;所以我选择redhat的长期支持版本 linux上执行&#xff1a; wget https://get.jenkins.io/redhat-stable/jenkins-2.222.1-1.1.noarch.rpm安装 使用rpm安装&#xf…

【Linunx报错】程序在运行时无法找到一个名为 “libctemplate.so.3“ 的共享库文件

第一个报错&#xff1a; error while loading shared libraries: libctemplate.so.3: cannot open shared object file: No such file or directory 解决方法&#xff1a; 这个错误信息提示你的程序在运行时无法找到一个名为 “libctemplate.so.3” 的共享库文件&#xff0c;因…

GAMES302等几何分析(IGA)---- 课程简介及等几何分析的介绍

文章目录 前言提纲产品数字化设计\仿真\优化全流程介绍计算机辅助设计&#xff08;CAD&#xff09;NURBS理论基础计算机辅助工程&#xff08;CAE&#xff09;什么是CAE为什么用CAECAE典型应用CAE解决问题的一般过程CAE方法体系及软件 结构优化创成式设计设计仿真类工业软件国产…

mybatis注解的详解和开发(增、删、改、查以及一对一、一对多/多对一、多对多的关系联查)

mybatis注解的基本理解和开发(增、删、改、查以及一对一、一对多/多对一、多对多的关系联查) 使用mybatis注解开发的原因&#xff1f; 注解提供了一种简单的方式来实现简单映射语句&#xff0c;而不会引入大量的开销。能够读懂别人写的代码&#xff0c;特别是框架相关的代码。…

Java——反转链表

题目链接 牛客在线oj题——反转链表 题目描述 给定一个单链表的头结点pHead(该头节点是有值的&#xff0c;比如在下图&#xff0c;它的val是1)&#xff0c;长度为n&#xff0c;反转该链表后&#xff0c;返回新链表的表头。 数据范围&#xff1a; 0≤n≤1000 要求&#xff1…

OpenAI最新官方ChatGPT聊天插件接口《插件示例demo》全网最详细中英文实用指南和教程,助你零基础快速轻松掌握全新技术(四)(附源码)

Example plugins 插件示例demo 前言Introduction 导言Learn how to build a simple todo list plugin with no auth 了解如何构建一个简单的待办事项列表插件&#xff0c;无需授权Learn how to build a simple todo list plugin with service level auth 了解如何构建一个简单的…

【Unity VR开发】结合VRTK4.0:瞬移点

语录&#xff1a; 如果把童年再放映一遍&#xff0c;我们一定会先大笑&#xff0c;然后放声痛哭&#xff0c;最后挂着泪&#xff0c;微笑着睡去。 前言&#xff1a; 移动的限制除了设置移动区域&#xff0c;也可以使用瞬移点&#xff1a;Locomotors.TeleportTargets.Point。 正…

HQChart报价列表高级应用教程7-创建走势图列

HQChart报价列表高级应用教程7-创建走势图列 走势图列效果图步骤1. 走势图列数据截图数据结构HQChart代码地址走势图列 在行情报价里面,使用单独的一列显示每一个股票的价格走势的缩略图。 效果图 步骤 1. 走势图列 REPORT_COLUMN_ID.CLOSE_LINE_ID 走势图列在创建报价列…

ChatGPT: 人工智能对话模型的前沿技术与应用探析

ChatGPT: 人工智能对话模型的前沿技术与应用探析 引言 ChatGPT作为一种人工智能对话模型&#xff0c;在近年来引起了广泛的关注和研究。随着人工智能技术的不断发展&#xff0c;ChatGPT作为一种前沿技术在人机对话领域具有重要地位和广泛的应用价值。本文将介绍ChatGPT的背景和…

【CocosCreator入门】CocosCreator组件 | ProgressBar(进度条)组件

Cocos Creator 是一款流行的游戏开发引擎&#xff0c;具有丰富的组件和工具&#xff0c;其中的ProgressBar组件是一种用于实现进度条效果的重要组件。它可以让我们在游戏中展示各种进度条效果&#xff0c;例如加载进度条、血条等。 目录 一、组件介绍 二、组件属性 三、脚本…

如何删除docker镜像与容器

目录 删除示例&#xff1a; 1.查看docker中要删除的镜像 2.删除镜像&#xff0c;使用命令“docker rmi image id” 3.查看docker中正在运行的容器 4.停止容器 5.删除容器 6.查看容器 7.删除镜像 8.最后查看所有镜像 删除示例&#xff1a; 1.查看docker中要删除的镜像 …