【OBS】SpringBoot + Vue + el-upload 通过临时 URL 上传文件到 OBS

news2024/11/25 4:57:53

华为云OBS的官方文档(链接:https://support.huaweicloud.com/sdk-java-devg-obs/obs_21_0901.html#section1)中关于上传文件的内容,只提供了使用JAVA获取临时上传链接,并使用JAVA创建请求上传纯文本的方法。想要把这部分内容应用到 SpringBoot + Vue + ElementUI/Element-Plus 中,还差很多东西。

文章目录

  • 0 前提条件
  • 1 OBS 桶创建和配置
    • 1.1 华为云OBS桶的创建
    • 1.2 配置桶允许跨域请求
    • 1.3 获取桶信息
  • 2 SpringBoot 后端配置
    • 2.1 依赖
    • 2.2 application.properties 配置
    • 2.3 工具类
    • 2.4 Controller
  • 3 Vue 前端配置
    • 3.1 Vue 组件
    • 3.2 upload API
    • 3.3 request.js

0 前提条件

请先确保SpringBoot、Vue、ElementUI/Element-Plus、axios 等工具安装和配置正确

笔者使用环境:SpringBoot 3.1.0, Vue 3, Element-Plus
SpringBoot 2.7 和 Vue 2 按理不会有很大区别,如有需要请自行调整代码

1 OBS 桶创建和配置

1.1 华为云OBS桶的创建

可参考如下配置
在这里插入图片描述

1.2 配置桶允许跨域请求

可参考官方文档:https://support.huaweicloud.com/sdk-browserjs-devg-obs/obs_24_0201.html

其中允许的来源设置为 * 即允许所有跨域请求,也可按如下设置,仅允许当前本地前端访问,其中 8080 为 Vue 前端端口:

http://localhost:8080
http://127.0.0.1:8080

补充头域 可留空

1.3 获取桶信息

后边需要用到的信息有:bucketName、accessKeyId、securitAccessKey、endPoint

bucketName: 本文1.1中创建桶时自定义的桶名称;
accessKeyId 和 securitAccessKey: 参考官方文档https://support.huaweicloud.com/usermanual-ca/zh-cn_topic_0046606340.html;
endPoint:参考下图
在这里插入图片描述

2 SpringBoot 后端配置

2.1 依赖

        <dependency>
            <groupId>com.huaweicloud</groupId>
            <artifactId>esdk-obs-java</artifactId>  <!-- 华为云依赖 -->
            <version>3.22.12</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>  <!-- log日志 -->
            <optional>true</optional>
        </dependency>

2.2 application.properties 配置

application.properties 添加如下配置,值为本文1.3获取的桶信息

huaweicloud.obs.accessKey=
huaweicloud.obs.securityKey=
huaweicloud.obs.endPoint=
huaweicloud.obs.bucketName=
huaweicloud.obs.path =

2.3 工具类

com.gabriel.docsharing.utils 创建如下工具类:

package com.gabriel.docsharing.utils;

import com.obs.services.ObsClient;
import com.obs.services.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class HuaweiOBS {
    
    @Value("${huaweicloud.obs.accessKey}")
    private String ak;
    
    @Value("${huaweicloud.obs.securityKey}")
    private String sk;
    
    @Value("${huaweicloud.obs.bucketName}")
    private String bucketName;
    
    @Value("${huaweicloud.obs.endPoint}")
    private String endpoint;
    
    // 文件目录
    private final String prifix = "/test";
    
    /**
     * 获取上传地址
     *
     * @param fileName 文件名称
     * @param fileType 文件路径
     * @return
     */
    public String getUploadUrl(String fileName, FileType fileType) {
        try {
            // 创建ObsClient实例
            ObsClient obsClient = new ObsClient(ak, sk, endpoint);
            // URL有效期,3600秒
            long expireSeconds = 3600L;
            Map<String, String> headers = new HashMap<String, String>();
            headers.put("Content-Type", "application/octet-stream");
            String objectName = fileType.getType().concat("/").concat(fileName);
            TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.PUT, expireSeconds);
            request.setBucketName(bucketName);
            request.setObjectKey(objectName);
            request.setHeaders(headers);
            TemporarySignatureResponse response = obsClient.createTemporarySignature(request);
            return response.getSignedUrl();
        } catch (Exception e) {
            log.error("获取上传地址异常:{}", e.getMessage(), e);
        }
        return null;
    }
    
    public enum FileType {
        TEST("test", "测试"),
        PDF("pdf","PDF文件");
        
        private String type;
        private String desc;
        
        FileType(String type, String desc) {
            this.type = type;
            this.desc = desc;
        }
        
        public String getType() {
            return type;
        }
        
        public String getDesc() {
            return desc;
        }
    }
}

2.4 Controller

com.gabriel.docsharing.controller 创建如下 Controller:

package com.gabriel.docsharing.controller;

import com.gabriel.docsharing.utils.HuaweiOBS;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 *  前端控制器
 * 
 * @author Gabriel
 * @since 2023-06-08
 */
@Log
@RestController
@RequestMapping("/doc")
public class DocController {
    @Autowired
    HuaweiOBS huaweiOBS;
    
    @RequestMapping(value = "/getUploadUrl", method = RequestMethod.GET)
    public String getUploadUrl(String filename){
        String url = huaweiOBS.getUploadUrl(filename, HuaweiOBS.FileType.TEST);
        log.info("get upload url, filename: "+ filename + " result: " + url);
        return url;
    }
}

3 Vue 前端配置

3.1 Vue 组件

创建 Upload.vue 文件(请自行设置路由),内容如下:

<template>
  <el-upload class="upload" ref="upload" drag
             :http-request="uploadAction"
             :limit="1"
             :auto-upload="false"
             :on-change="fileChange"
             :on-exceed="handleExceed">
    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  </el-upload>
  <el-button @click="submitForm">上传</el-button>
</template>

<script>
import {genFileId} from "element-plus";
import {useUploadApi} from "@/api/upload";

export default {
  name: "Upload",
  data() {
    return {
      uploadUrl: ''
    }
  },
  methods: {
    fileChange(file) {  // 上传文件发生变化时,根据新文件获取上传链接
      if (!this.checkDoc(file)) {
        this.$refs.upload.clearFiles();
      } else {
        useUploadApi().getUploadUrl(file.name).then((res) => {
          this.uploadUrl = res;
        });
      }
    },
    handleExceed(files) {  // 上传第二个文件时,覆盖第一个文件
      if (this.checkDoc(files[0])) {
        this.$refs.upload.clearFiles()
        let file = files[0]
        file.uid = genFileId()
        this.$refs.upload.handleStart(file)
      }
    },
    checkDoc(file) {
      // 文件大小和格式检查
      // let index = file.name.lastIndexOf(".");
      // let extension = file.name.substr(index + 1);
      // let extensionList = ["jpeg"];
      // const isLt2M = file.size / 1024 / 1024 < 1;
      // if (!isLt2M) {
      //   ElMessage.error("文件不可超出1M");
      //   return false;
      // } else if (extensionList.indexOf(extension) < 0) {
      //   ElMessage.error("当前文件格式不支持");
      //   return false;
      // } else {
      //   return true;
      // }
      return true;
    },
    submitForm() {  // 提交上传
      this.$refs.upload.submit();
    },
    uploadAction(param){  // 提交时的自定义上传配置
      useUploadApi().uploadFile(this.uploadUrl, param.file).then(res=>{
        alert("上传完成,请在检查中查看返回状态")
      })
    },
  },
}
</script>

3.2 upload API

创建 api/upload/index.js 文件,内容如下:

import request from '@/utils/request';

/**
 * 上传文件api接口集合
 * @method signIn 用户登录
 * @method signOut 用户退出登录
 */
export function useUploadApi() {
    return {
        getUploadUrl: (filename) => {
            return request({
                url: '/api/doc/getUploadUrl?filename=' + filename,
                method: 'get'
            });
        },
        uploadFile: (url, file) => {
            return request({
                url: url,
                method: 'put',
                headers:{'Content-Type': 'application/octet-stream'},
                data: file
            });
        }
    };
}

3.3 request.js

创建 utils/request.js 文件,内容如下:

import axios from 'axios';

// 创建 axios 实例
const service = axios.create({
	baseURL: process.env.VUE_APP_BASE_API,
	timeout: 50000,
});

export default service;

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

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

相关文章

离线分析fsimage文件进行数据深度分析

以离线分析FsImage文件进行数据深度分析 整个方案的基本架构&#xff1a; FsImage文件时HDFS存放在NameNode中的镜像文件&#xff0c;里面包括了整个HDFS集群的目录和文件信息&#xff0c;(类似于一个索引目录部分数据的文件)&#xff0c;而且HDFS提供了命令可以将FsImage文件…

【严重】VMware Aria Operations for Networks 远程代码执行漏洞(存在POC)

漏洞描述 VMware Aria Operations for Networks (前名为vRealize Network Insight)是 VMware 公司提供的一款网络可视性和分析工具&#xff0c;用于优化网络性能或管理各种VMware和Kubernetes部署。 VMware Aria Operations for Networks 6.x版本中由于 createSupportBundle…

How to fix the global rice crisis 如何应对全球稻米危机 | 经济学人20230401版双语精翻

4月1日《经济学人》周报封面即社论区&#xff08;Leaders&#xff09;精选文章&#xff1a;《如何应对全球稻米危机》&#xff08;How to fix the global rice crisis&#xff09;。 “民以食为天”语出《孟子公孙丑上》&#xff0c;强调&#xff1a;人民的生命福祉和国家的繁荣…

每日一练 | 华为认证真题练习Day62

1、广播地址是网络地址中主机位全部置为1的一种特殊地址&#xff0c;它也可以做为主机地址使用。 A. True B. False 2、如图所示&#xff0c;如果管理员希望能够提升此网络的性能&#xff0c;则下面哪一种方法最合适&#xff1f; A. 使用交换机把每台主机连接起来&#xff0c…

java8 (jdk 1.8) 新特性——Stream ApI以及具体实例

在java8 中&#xff0c;有两个最重要的改变&#xff0c;一个就是之前了解的Lmbda java8 (jdk 1.8) 新特性——Lambda ,还有一个就是Stream Api 1. 什么是Stream API 简单来说就是一个类库&#xff0c;里边有一些方法方便我们对集合数据进行操作&#xff0c;就好像使用 SQL 语…

是单例模式,不是单身

✍&#x1f3fc;作者&#xff1a;周棋洛&#xff0c;计算机学生 ♉星座&#xff1a;金牛座 &#x1f3e0;主页&#xff1a;点击学习更多 &#x1f310;关键&#xff1a;JavaScript 单例 设计模式 单例模式的定义是&#xff1a;保证一个类仅有一个实例&#xff0c;并提供一个访问…

数据结构05:树与二叉树[C++][线索二叉树:先序、中序、后序]

图源&#xff1a;文心一言 考研笔记整理1.4W字&#xff0c;小白友好、代码先、中序可跑&#xff0c;后序代码有点问题仅作记录~~&#x1f95d;&#x1f95d; 第1版&#xff1a;查资料、写BUG、画导图、画配图~&#x1f9e9;&#x1f9e9; 参考用书&#xff1a;王道考研《2024…

领域事件解读

文章目录 EventBus简介DDD领域事件架构简析快速入门pom依赖bean配置PublisherSubscriber 设计原理PublisherSubscriber 事件总线(EventBus)&#xff0c;设计初衷是解耦系统模块&#xff0c;将系统中的各类业务操作抽象为事件模型&#xff0c;我们把产生事件的部分称之为事件的发…

电容笔哪个厂家的产品比较好?时下热门的平替苹果笔

苹果原装的Pencil&#xff0c;在市场上可是炙手可热的&#xff0c;而且苹果的这款pencil&#xff0c;也不是什么便宜的。当然&#xff0c;你可以用这个苹果笔搭配iPad&#xff0c;不过&#xff0c;如果你不想花很多钱&#xff0c;那就可以换一支普通的平替电容笔。就当前的技术…

一篇搞定C语言操作符(详解含示例)

目录 一.操作符是什么&#xff1f; 基本特征 语义 优先级 结合性 二.操作符的分类 三.操作符各类详解 1.算数操作符&#xff08; - * / %&#xff09; &#xff08;1&#xff09;优先级&#xff1a; &#xff08;2&#xff09;除法操作符&#xff08;…

数学基础-标量,向量,张量

前言 数学中&#xff0c;如何描述事务&#xff0c;以棍子为例子&#xff1a; 棍子的长度棍子方向棍子转向… 标量 单纯的形容事务的一个特征&#xff0c;如果体积&#xff0c;长度。 向量 指具有大小&#xff08;magnitude&#xff09;和方向的量。它可以形象化地表示为带…

利用腾讯云推流做7*24小时云直播

早在10年前&#xff0c;直播刚刚火的的时候&#xff0c;我就写过一个基于RTMP推流的直播工具&#xff0c;但没有利用起来&#xff0c;一直荒废了。想想真是可惜&#xff0c;不过谁怪咱精力有限切没有商业头脑呢。 最近刷B站&#xff0c;一位UP分享了无人值守的云直播方案&…

21JS12——内置对象

文章目录 一、内置对象二、查文档1、 MDN2、如何学习对象中的方法 三、Math对象1、Math对象2、案例-封装自己的数学对象3、Math的几个方法&#xff08;1&#xff09;绝对值&#xff08;2&#xff09;三个取整方法&#xff08;3&#xff09;随机数方法random&#xff08;&#x…

【深度学习】3-2 神经网络的学习- mini-batch学习

机器学习使用训练数据进行学习。使用训练数据进行学习&#xff0c;就是针对训练数据计算损失函数的值&#xff0c;也就是说,训练数据有100个的话&#xff0c;就要把这 100个损失函数的总和作为学习的指标。 求多个数据的损失函数&#xff0c;要求所有训练数据的损失函数的综合…

INTERSPEECH2023|达摩院语音实验室入选论文全况速览

近日&#xff0c;语音技术领域旗舰会议INTERSPEECH 2023公布了本届论文审稿结果&#xff0c;阿里巴巴达摩院语音实验室有17篇论文被大会收录。 01 论文题目&#xff1a;FunASR: A Fundamental End-to-End Speech Recognition Toolkit 论文作者&#xff1a;高志付&#xff0c;…

基于 AntV G2Plot 来实现一个 堆叠柱状图 加 折线图 的多图层案例

前言 最近研究了一下antv/g2的组合图例&#xff0c;并尝试做了一个不算太难的组合图&#xff0c;下面介绍一下整个图里的实现过程。 最终效果图 先来看一下最终的效果图 该图表有两部分组成&#xff0c;一部分是柱状图&#xff0c;准确说是堆叠的柱状图&#xff0c;一个柱…

【TA100】图形 3.5 Early-z和Z-prepass

一、深度测试&#xff1a;Depth Test 1.回顾深度测试的内容 深度测试位于渲染管线哪个位置 ○ 深度测试位于逐片元操作中、模板测试后、透明度混合前 为什么做深度测试 ● 深度测试可以解决&#xff1a;物体的可见遮挡性问题 ○ 我们可以用一个例子说明 ■ 图的解释&…

windows应急整理

windows应急整理 Virustotal 网站分析恶意样本 BrowingHistoryView 查看浏览器所有历史记录,可能会请求攻击者的恶意网站或者下载东西 启动项检查 开机启动项文件夹 msconfig 注册表run 键值查看 启动项 临时文件检查,temp 目录权限特殊,容易成为被利用对象 %temp%查看 tem…

华为HCIP第一天---------RSTP

一、介绍 1、以太网交换网络中为了进行链路备份&#xff0c;提高网络可靠性&#xff0c;通常会使用冗余链路&#xff0c;但是这也带来了网络环路的问题。网络环路会引发广播风暴和MAC地址表震荡等问题&#xff0c;导致用户通信质量差&#xff0c;甚至通信中断。为了解决交换网…