Springboot集成华为云OBS

2023-10-31

Springboot实现华为云对象存储OBS文件上传下载



前言

OBS入门,注册账号、获取ak\sk、创建桶示例:https://support.huaweicloud.com/qs-obs/obs_qs_1000.html


一、OBS是什么?

对象存储服务(OBS)可以提供海量、安全、高可靠、低成本的数据存储能力,适用于大数据分析、静态网站托管、在线视频点播等场景。废话不多说,请允许我娓娓道来!

二、使用步骤

1.引入依赖

<dependency>
            <groupId>com.huaweicloud</groupId>
            <artifactId>esdk-obs-java</artifactId>
            <version>3.20.6.1</version>
</dependency>

2.HuaweiyunOss工具类


package com.test.aliyunApi;

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

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class HuaweiyunOss {

    @Value("${huaweiyun.obs.ak}")//ak
    private String ak;
    @Value("${huaweiyun.obs.sk}")//sk
    private String sk;
    @Value("${huaweiyun.obs.bucketName}")//桶名称
    private String bucketName;
    @Value("${huaweiyun.obs.endpoint}")//终端节点访问
    private String endpoint;

    /**
     * 上传文件--流式
     * @param fileName 上传文件名称
     * @param fileType 文件路径
     * @param is 文件流
     * @return
     */
    public boolean uploadFile(String fileName, FileType fileType, InputStream is) {
        ObsClient obsClient = null;
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            obsClient = new ObsClient(ak, sk, endpoint);
            HeaderResponse response = obsClient.putObject(bucketName, objectName, is);
            // 可选:调用成功后,记录调用成功的HTTP状态码和服务端请求ID
            int statusCode = response.getStatusCode();
            if (200 == statusCode) {
                return true;
            }
            obsClient.close();
        } catch (IOException e) {
            log.info("文件上传失败:{}", e.getMessage(), e);
        }
        return false;
    }

    /**
     * 上传文件--字节数组
     * @param fileName 上传文件名称
     * @param fileType 文件路径
     * @param is 文件流
     * @return
     */
    public boolean uploadFileByte(String fileName, FileType fileType, byte[] is) {
        ObsClient obsClient = null;
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            obsClient = new ObsClient(ak, sk, endpoint);
            HeaderResponse response = obsClient.putObject(bucketName, objectName, new ByteArrayInputStream(is));
            // 可选:调用成功后,记录调用成功的HTTP状态码和服务端请求ID
            int statusCode = response.getStatusCode();
            if (200 == statusCode) {
                return true;
            }
            obsClient.close();
        } catch (IOException e) {
            log.info("文件上传失败:{}", e.getMessage(), e);
        }
        return false;
    }

    /**
     * 下载文件
     * @param fileName 文件名称
     * @param fileType 文件路径
     * @return
     */
    public String getDownloadUrl(String fileName, FileType fileType) {
        ObsClient obsClient = null;
        obsClient = new ObsClient(ak, sk, endpoint);
        // URL有效期,3600秒.5分钟
        long expireSeconds = 3600L;
        String objectName = fileType.getType().concat("/").concat(fileName);
        TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, expireSeconds);
        request.setBucketName(bucketName);
        request.setObjectKey(objectName);
        TemporarySignatureResponse response = obsClient.createTemporarySignature(request);
        return response.getSignedUrl();
    }

    /**
     * 获取上传地址
     * @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;
    }

    /**
     * 下载文件返回字节数组
     * @param fileName 文件名称
     * @param fileType 文件路径
     * @return
     */
    public byte[] downloadFile(String fileName, FileType fileType) {
        try {
            InputStream inputStream = downloadFileInputStream(fileName, fileType);
            byte[] bytes = IOUtils.toByteArray(inputStream);
            return bytes;
        } catch (Exception e) {
            log.error("下载文件异常:{}", e.getMessage(), e);
        }
        return null;
    }
    /**
     * 上传视频
     * @param fileName 文件名称
     * @param fileType 文件路径
     * @return
     */
    public boolean uploadFileVideo(String fileName, FileType fileType, InputStream is) {
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            ObsClient obsClient = new ObsClient(ak, sk, endpoint);
            // 添加 ContentType (添加后可在浏览器中直接浏览,而非下载链接)
            obsClient.putObject(bucketName, objectName, is);
            obsClient.close();
            return true;
        } catch (Exception e) {
            log.error("上传视频文件异常:{}", e.getMessage(), e);
        }
        return false;
    }

    /**
     * 下载文件返回流式
     * @param fileName 文件名称
     * @param fileType 文件路径
     * @return
     */
    public InputStream downloadFileInputStream(String fileName, FileType fileType) {
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            // 用户拿到STS临时凭证后,通过其中的安全令牌(SecurityToken)和临时访问密钥(AccessKeyId和AccessKeySecret)生成OSSClient。
            ObsClient obsClient = new ObsClient(ak, sk, endpoint);
            ObsObject obsObject = obsClient.getObject(bucketName, objectName);
            obsClient.close();
            return obsObject.getObjectContent();
        } catch (Exception e) {
            log.error("下载文件异常:{}", e.getMessage(), e);
        }
        return null;
    }


    public enum FileType {
        TEST("TEST", "测试")
        ;

        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;
        }
    }
}

3.上传下载测试

	@Autowired
    private HuaweiyunOss huaweiyunOss;
	/**
	 * 上传图片并下载返回预览地址
	 * @param file
	 * @return
	 * @throws IOException
	*/
	@PostMapping("/pic")
	@ApiOperation(value = "上传图片", notes = "上传图片")
	public Response<?> pic(MultipartFile file) throws IOException {
		String fileName = file.getOriginalFilename();
		boolean isOk = huaweiyunOss.uploadFile(fileName, HuaweiyunOss.FileType.TEST, file.getInputStream());
		String downloadUrl = huaweiyunOss.getDownloadUrl(fileName, HuaweiyunOss.FileType.TEST);
		Map<String,Object> map = new HashMap<>();
		map.put("downloadUrl",downloadUrl);
		map.put("fileName",fileName);
		return isOk ? Response.success(map) : Response.error("文件上传失败");
	}
	/**
	 * 上传视频并下载返回预览地址
	 * @param file
	 * @return
	 * @throws IOException
	*/
	@PostMapping("/video")
	@ApiOperation(value = "上传视频", notes = "上传视频")
	public Response<?> video(MultipartFile file) throws IOException {
		String fileName = file.getOriginalFilename();
		boolean isOk = huaweiyunOss.uploadFileVideo(fileName, HuaweiyunOss.FileType.TEST, file.getInputStream());
		String downloadUrl = huaweiyunOss.getDownloadUrl(fileName, HuaweiyunOss.FileType.TEST);
		Map<String,Object> map = new HashMap<>();
		map.put("downloadUrl",downloadUrl);
		map.put("fileName",fileName);
		return isOk ? Response.success(map) : Response.error("文件上传失败");
	}
	/**
	 * 获取上传地址
	 * @param picName
	 * @return
	 * @throws IOException
	*/
	 String videoUploadUrl = huaweiyunOss.getUploadUrl(picName, HuaweiyunOss.FileType.TEST);
	/**
     * 下载文件返回字节数组
     * @param fileName 文件名称
     * @param fileType 文件路径
     * @return
    */
    public byte[] downloadFile(String fileName, FileType fileType) {
        try {
            InputStream inputStream = downloadFileInputStream(fileName, fileType);
            byte[] bytes = IOUtils.toByteArray(inputStream);
            return bytes;
        } catch (Exception e) {
            log.error("下载文件异常:{}", e.getMessage(), e);
        }
        return null;
    }


总结

 OBS提供了四种存储类别:标准存储、低频访问存储、归档存储、深度归档存储(受限公测中),从而满足客户业务对存储性能、成本的不同诉求。自我感觉喝OSS用法一样,只是调用的方法不一样而已,欢迎探讨!
    1、标准存储访问时延低和吞吐量高,因而适用于有大量热点文件(平均一个月多次)或小文件(小于1MB),且需要频繁访问数据的业务场景,例如:大数据、移动应用、热点视频、社交图片等场景。
    2、低频访问存储适用于不频繁访问(平均一年少于12次)但在需要时也要求快速访问数据的业务场景,例如:文件同步/共享、企业备份等		  
    场景。与标准存储相比,低频访问存储有相同的数据持久性、吞吐量以及访问时延,且成本较低,但是可用性略低于标准存储。
    3、归档存储适用于很少访问(平均一年访问一次)数据的业务场景,例如:数据归档、长期备份等场景。归档存储安全、持久且成本极低,可以用来替代磁带库。为了保持成本低廉,数据取回时间可能长达数分钟到数小时不等。
    4、深度归档存储适用于长期不访问(平均几年访问一次)数据的业务场景,其成本相比归档存储更低,但相应的数据取回时间将更长,一般为数小时。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Springboot集成华为云OBS 的相关文章

  • Mockito 在调用参数数量可变的方法时使用参数匹配器

    我试图在对具有可变数量参数的方法的调用中使用参数匹配器 Java 中的东西 没有成功 我的代码如下 我还将列出我尝试用来完成此工作的所有行 import static org mockito Mockito public class Met
  • 如何将 javax.persistence.Column 定义为 Unsigned TINYINT?

    我正在基于 MySQL 数据库中的现有表创建 Java 持久性实体 Bean 使用 NetBeans IDE 8 0 1 我在这个表中遇到了一个字段 其类型为 无符号 TINYINT 3 我发现可以执行以下操作将列的类型定义为 unsign
  • Spring Security 自定义过滤器

    我想自定义 Spring security 3 0 5 并将登录 URL 更改为 login 而不是 j spring security check 我需要做的是允许登录 目录并保护 admin report html 页面 首先 我使用教
  • Java:无法从同一包中的不同类访问静态变量

    这很奇怪 因为我有一个可以访问 Frame dimension getWidth 的 Character 类 及其伙伴 getHeight 但是当我想在 Map 类中使用它时 Eclipse 强调了它并且无法给我反馈 运行该程序最终会出现
  • 通过SOCKS代理连接Kafka

    我有一个在 AWS 上运行的 Kafka 集群 我想用标准连接到集群卡夫卡控制台消费者从我的应用程序服务器 应用程序服务器可以通过 SOCKS 代理访问互联网 无需身份验证 如何告诉 Kafka 客户端通过代理进行连接 我尝试了很多事情 包
  • 如何在 Antlr4 中为零参数函数编写语法

    我的函数具有参数语法 如下面的词法分析器和解析器 MyFunctionsLexer g4 lexer grammar MyFunctionsLexer FUNCTION FUNCTION NAME A Za z0 9 DOT COMMA L
  • 通往楼梯顶部的可能路径

    这是一个非常经典的问题 我听说谷歌在他们的面试中使用过这个问题 问题 制定一个递归方法 打印从楼梯底部到楼梯顶部的所有可能的独特路径 有 n 个楼梯 您一次只能走 1 步或 2 步 示例输出 如果它是一个有 3 级楼梯的楼梯 1 1 1 2
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • 大数据使用什么数据结构

    我有一个包含一百万行的 Excel 工作表 每行有 100 列 每行代表一个具有 100 个属性的类的实例 列值是这些属性的值 哪种数据结构最适合在这里使用来存储数百万个数据实例 Thanks 这实际上取决于您需要如何访问这些数据以及您想要
  • 如何使用 Hibernate (EntityManager) 或 JPA 调用 Oracle 函数或过程

    我有一个返回 sys refcursor 的 Oracle 函数 当我使用 Hibernate 调用该函数时 出现以下异常 Hibernate call my function org hibernate exception Generic
  • 使用 Guice 优化注册表

    你好 今天思考了一种优化 有一些疑问 语境 我正在使用 Guice 2 进行 Java 开发 在我的网络应用程序中 我有一个转换器注册表 可以即时转换为某种类型 转换器描述如下 public class StringToBoolean im
  • 如何在 Spring 属性中进行算术运算?

  • 流中的非终结符 forEach() ?

    有时 在处理 Java Stream 时 我发现自己需要一个非终端 forEach 来触发副作用但不终止处理 我怀疑我可以用 map item gt f item 之类的方法来做到这一点 其中方法 f 执行副作用并将项目返回到流中 但这似乎
  • 如何在 Java 中创建接受多个值的单个注释

    我有一个名为 Retention RetentionPolicy SOURCE Target ElementType METHOD public interface JIRA The Key Bug number JIRA referenc
  • Hamcrest Matchers - 断言列表类型

    问题 我目前正在尝试使用 Hamcrest Matchers 来断言返回的列表类型是特定类型 例如 假设我的服务调用返回以下列表 List
  • 使用按钮作为列表的渲染器

    我想使用一个更复杂的渲染器 其中包含列表的多个组件 更准确地说 类似于this https stackoverflow com questions 10840498 java swing 1 6 textinput like firefox
  • OpenCSV:将嵌套 Bean 映射到 CSV 文件

    我正在尝试将 bean 映射到 CSV 文件 但问题是我的 bean 具有其他嵌套 bean 作为属性 所发生的情况是 OpenCSV 遍历属性找到一个 bean 然后进入其中并映射该 bean 内的所有数据 如果找到另一个 bean 它就
  • org.apache.commons.net.io.CopyStreamException:复制时捕获 IOException

    我正在尝试使用以下方法中的代码将在我的服务器中创建的一些文件复制到 FTP 但奇怪的是我随机地低于错误 我无法弄清楚发生了什么 Exception org apache commons net io CopyStreamException
  • Java EE 目录结构

    我对以下教程有疑问 http www mkyong com jsf2 jsf 2 internationalization example http www mkyong com jsf2 jsf 2 internationalizatio
  • Spring表单ModelAttribute字段验证避免400 Bad Request错误

    我有一个ArticleFormModel包含正常发送的数据html form由 Spring 使用注入 ModelAttribute注释 即 RequestMapping value edit method RequestMethod PO

随机推荐

  • 【HJ72】百钱买百鸡问题

    题目描述 公元前五世纪 我国古代数学家张丘建在 算经 一书中提出了 百鸡问题 鸡翁一值钱五 鸡母一值钱三 鸡雏三值钱一 百钱买百鸡 问鸡翁 鸡母 鸡雏各几何 现要求你打印出所有花一百元买一百只鸡的方式 输入描述 输入任何一个整数 即可运行程
  • 从浏览器地址栏输入url到显示页面的步骤

    浏览器输入URL到渲染过程解析 从浏览器地址栏输入url到显示页面的步骤 从浏览器地址栏输入url到显示页面的步骤 目录 1 概述 2 DNS域名解析 3 三次握手与四次挥手 4 DOM CSSOM 渲染树的构建 渲染与绘制 1 概述 浏览
  • Mac里的airdrop传输文件

    01 两方打开 02 设置对所有人可以发现 03 右键需要传输的文件 04 选择共享 airdrop 05 点击页面上的名称 开始传输 note 可以传输 app文件 这样可以大大节省下载安装所要耗费的时间 word只要一分钟就能从从无到有
  • 机器学习_深度学习毕设题目汇总——图像生成

    下面是该类的一些题目 题目 基于生成式对抗网络的无监督图像生成研究 用于图像生成的机器学习算法在人像合成中的研究与应用 可抵抗相机抖动的高动态图像生成算法研究 图像生成诗歌的端到端模型研究 基于GANs的脑部MRI图像生成方法研究 基于GA
  • 问二十四:分类说明JUC包常用类有哪些?

    JUC中常用类汇总 JUC的atomic包下运用了CAS的AtomicBoolean AtomicInteger AtomicReference等原子变量类 JUC的locks包下的AbstractQueuedSynchronizer AQ
  • 【Ensemble Learning】第 3 章:混合模型

    在第2章中 您学习了如何以不同方式划分和混合训练数据以构建集成模型 其性能优于在未划分数据集上训练的模型 在本章中 您将学习不同的组装方法 与混合训练数据方法不同 混合模型方法在不同的机器学习模型中使用相同的数据集 然后以不同的方式组合结果
  • pads win10显示不全

    打开注册表 WIN R 1 路径 HKEY LOCAL MACHINE SOFTWARE Microsoft Windows NT CurrentVersion Fonts 将原来的 Microsoft YaHei TrueType Mic
  • C++ Vector容器的push_back( )与pop_back( )函数

    C Vector容器的push back 与pop back 函数 push back pop back 参考链接 push back 函数将一个新的元素加到vector的最后面 位置为当前最后一个元素的下一个元素 push back 在V
  • java IDEA加密/解密 源码

    package tool import org apache commons codec binary Base64 import org bouncycastle jce provider BouncyCastleProvider imp
  • Git如何Check Out出指定文件或者文件夹

    原文 http www handaoliang com a 20140506 195406 html 在进行项目开发的时候 有时候会有这样的需求那就是 我们只希望从Git仓库里取指定的文件或者文件夹出来 在SVN里面 这非常容易实现 因为S
  • 实训9——门磁报警

    实验九 门磁报警 一 实验目的 通过门磁传感器 判断三种开门方式 1 正常开门 就是有正常开门方式 例指纹开门 蓝牙开门后 主人打开门 触发门磁 2 门未关好 在正常开门后 主人没有即使关门 会引发门未关好报警 3 有人撬门 非正常开门 即
  • [Python人工智能] 十五.无监督学习Autoencoder原理及聚类可视化案例详解

    从本专栏开始 作者正式研究Python深度学习 神经网络及人工智能相关知识 前一篇文章详细讲解了循环神经网络LSTM RNN如何实现回归预测 通过sin曲线拟合实现如下图所示效果 本篇文章将分享无监督学习Autoencoder的原理知识 然
  • 用户增长漫谈二

    除了功能迭代 增量开发配套敏捷理念 这里重要谈一个概念 宏观 微观上都有可取之处 品牌架构 反应企业意愿 个性 未来可能性留存 兼容不同利益群体方式进程商业活动 主品牌 标识性弱 但是个性强烈 业务 产品特性底的处理方式 以资金 实力彰显
  • MyBatis 学习笔记(八)---源码分析篇--SQL 执行过程详细分析

    前言 在面试中我们经常会被到MyBatis中 占位符与 占位符的区别 大多数的小伙伴都可以脱口而出 会对值进行转义 防止SQL注入 而 则会原样输出传入值 不会对传入值做任何处理 本文将通过源码层面分析为啥 可以防止SQL注入 源码解析 首
  • JS逆向爬虫案例分享

    某域网站数据爬取之反爬策略JS逆向分析 本次分享解析某域网站数据的反爬机制 此次只做技术分享 如有侵权 请联系删除 1 分析网 首先打开网站发送请求 点击F12 发送请求发现电脑端并没有接口返回数据 即返回切换手机端观察 点解F12观察找到
  • Mplayer 1.0pre5 安装纪实

    一开始装了个realone gold 版 但是怎么弄都没有声音 没有办法 只能硬着头皮装mplayer 了 刚刚接触linux 真的是什么也不懂 连看个电影也得费这么大的事 搞了一天 终于算是能看到图像和声音来 现在是只其然 但不怎么知所以
  • 【医学图像分割】读论文系列 1

    医学图像分割 读论文系列 1 文章目录 医学图像分割 读论文系列 1 Title Introduction Abstract Keyword Method Experiment Conclusion Title 标题 Noisy Label
  • JS - 手写节流、防抖

    目录 节流 解释 手写实现 全部计时器实现 Date now 时间戳实现 混合 防抖 解释 手写实现 节流 解释 节流 throttle 是指让某一个函数的触发次数在一定时间内限定在一定范围内 最常的情况是一定时间内只触发最初的一次 常用在
  • 01_Numpy的图片处理(读取,变换,保存)

    Numpy的图片处理 读取 变换 保存 使用Numpy的ndarray可以读取图片文件 并且可以对图片进行各种各样的处理 例如 图片像素值的读取 替换 随机剪裁 拼接等等都可以使用ndarray 对于已经习惯使用Numpy的人们来说 已经可
  • Springboot集成华为云OBS

    Springboot实现华为云对象存储OBS文件上传下载 文章目录 Springboot实现华为云对象存储OBS文件上传下载 前言 一 OBS是什么 二 使用步骤 1 引入依赖 2 HuaweiyunOss工具类 3 上传下载测试 总结 前