文件存储解决方案-云存储阿里 OSS

news2024/11/20 14:23:51

文件存储解决方案-云存储阿里 OSS

1.文件存储(上传)解决方案讨论

1.图解

  • 文件存储解决方案-云存储阿里 OSS

image-20221113152120004

解读上图

  1. 普通上传并不是分布式,也不是集群,可用性不高
  2. 普通上传的分布式情况,使用了集群,但是当把文件存储在集群中的某台服务器,当下次读取时,因为负载均衡,存在读取不到的文件问题
  3. 应用服务器使用集群,文件存储通过网关提供统一接口来存储文件,可用性高
    3.1 方案 1: 自建服务器,成本高, 也存在技术瓶颈
    3.2 方案 2: 使用云存储产品(阿里云等), 是企业优选方案

2.对应 分布式 微服务 架构分析

2.阿里云对象存储介绍

1.官网

https://www.aliyun.com/product/oss

2.说明

阿里云对象存储 OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,提供数据高可用性, 多种存储类型供选择,全面优化存储成本

3.上传方式

1.普通上传方式

1.阿里云对象存储-普通上传示意图

image-20221113152537146

2.分析

  • 上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。

  • 扩展性差:如果后续用户多了,应用服务器会成为瓶颈。

  • 费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,
    不通过应用服务器,那么将能省下几台应用服务器

2.服务端签名后直传

1.阿里云对象存储-服务端签名后直传示意图

image-20221113152649133

2.分析

  • Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。
  • 但服务端无法实时了解用户上传了多少文件,上传了什么文件。如果想实时了解用户
    上传了什么文件,可以采用服务端签名直传并设置上传回调

3.准备工作

1.注册一个阿里云账号,并完成认证

2.阿里云地址:https://www.aliyun.com/

3.创建阿里云对象 Bucket 创建并测试

4.创建 RAM 用户(访问控制 RAM(Resource Access Management)是阿里云提供的一项管理用户身份与资源访问权限的服务), 得到 accessKeyId 和 accessKeySecret (可以理解成是阿里云子用户的 id 和密码)

具体步骤可以参考:https://llinp.cn/articles/2022/01/02/1641105914205.html

5.将得到 endpoint , accessKeyId , accessKeySecret 填写到代码中, 并指定要上传的文
件路径, 阿里云哪个 Bucket 和上传后的文件名是什么

4.使用原生 SDK,上传文件到阿里云对象 Bucket

参考阿里云官方文档 https://help.aliyun.com/document_detail/84781.html#p-yqj-z1w-rl2

,这里我使用的是简单上传-上传文件流的方式。

1.创建一个boot项目引入依赖

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

2.编写如下一个测试类,进行测试。

@RestController
public class TestController {

    @RequestMapping("/test")
    public R test() {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "你的accessKeyId";
        String accessKeySecret = "你的accessKeySecret";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "你的bucketName";
        // 上传文件名 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "12.jpg";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        String filePath = "C:\\Users\\llp\\Desktop\\solo-fetchupload-7208404724819002506-m0Dvrtu.jpg";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            //文件输入流
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObject请求。 将文件流写入到objectName文件中
            ossClient.putObject(bucketName, objectName, inputStream);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return R.ok();
    }

}

image-20221113164918485

可以看到文件已经上传到阿里云oss服务器上了

image-20221113165057664

5.使用 SpringCloud Alibaba OSS 传文件到阿里云对象 Bucket

1.引入依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>

2.编写yaml

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.56.100:3306/llpliving_commodity?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.jdbc.Driver
  cloud:
    alicloud:
      oss:
        endpoint: 参考创建bucket时选择的归属区域
      access-key: 你的keyId
      secret-key: 你的keySecret
      bucket-name: 你的bucketName

3.编写测试类

    @Resource
    private OSSClient ossClient;

    @Value("${spring.cloud.alicloud.bucket-name}")
    private String bucketName;
    //上传指定的文件到bucket
    @RequestMapping("/test2")
    public R test2() throws FileNotFoundException {
        String filePath = "C:\\Users\\asus\\Desktop\\solo-fetchupload-7208404724819002506-m0Dvrtu.jpg";
        String objectName = "13.jpg";
        InputStream inputStream = new FileInputStream(filePath);
        ossClient.putObject(bucketName, objectName, inputStream);
        ossClient.shutdown();
        return R.ok();
    }

image-20221113182803195

6.完成服务端签名后直传

1.文档

https://help.aliyun.com/document_detail/31926.html

image-20221113182941885

2.代码示例

https://help.aliyun.com/document_detail/91868.htm

3.代码+配置实现

1.引入依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>

2.编写yaml

server:
  port: 7070

spring:
  cloud:
    alicloud:
      oss:
        endpoint: oss-cn-chengdu.hangzhou.com
      access-key: 你的accessKey
      secret-key: 你的secretKey
      bucket-name: 你的bucketName

3.配置类,从yaml配置文件中读取配置信息

@Data
@Component
@ConfigurationProperties("spring.cloud.alicloud")
public class OssProperties implements InitializingBean {

    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucketName;

    public static String ENDPOINT;
    public static String KEY_ID;
    public static String KEY_SECRET;
    public static String BUCKET_NAME;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.ENDPOINT = endpoint;
        this.KEY_ID = accessKey;
        this.KEY_SECRET = secretKey;
        this.BUCKET_NAME = bucketName;
        this.ENDPOINT = endpoint;
    }

}

4.编写测试类

@RestController
public class OssServiceController {

    //提示:这里的注入方式是 OSS 接口注入, 不要写成实现类了
    @Resource
    private OSS ossClient;

    /**
     * 获取文件上传签名/授权
     * 这段代码从阿里云示例文档拷贝, 并做修改,去掉暂时不用的代码
     *
     * @return
     */
    @RequestMapping("/oss/policy")
    public R policy() {
        // 填写Host地址,格式为https://bucketname.endpoint。
        String host = "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT;
        // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
        // 我们可以将文件按照 年-月-日的形式分目录存放在阿里云
        String format = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
        // 用户上传文件时指定的前缀。
        String dir = format + "/";
        // 创建ossClient实例。
        OSS ossClient = new OSSClientBuilder().build(OssProperties.ENDPOINT, OssProperties.KEY_ID, OssProperties.KEY_SECRET);
        Map<String, String> respMap = null;
        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", OssProperties.KEY_ID);
            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());
        }
        return R.ok().put("data", respMap);
    }
}

5.测试

浏览器: http://localhost:7070/oss/policy

image-20221116191313271

6.前端拿到policy凭证之后,通过policy直接上传到阿里云

image-20221116195005316

import http from '@/utils/httpRequest.js'
export function policy() {
   return  new Promise((resolve,reject)=>{
        http({
            //url: http.adornUrl("/oss/policy"),
            url: "http://localhost:7070/oss/policy",
            method: "get",
            params: http.adornParams({})
        }).then(({ data }) => {
            resolve(data);
        })
    });
}

7.前端拿到policy直接进行上传会存在跨域问题

image-20221116194409876

8.解决阿里云跨域问题, 设置跨域

数据安全-跨域设置

image-20221116195330606

9.再次上传,依然存在问题

image-20221116195425778

image-20221116195642252

10.再次上传,上传成功

image-20221116195717538

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

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

相关文章

数据结构每日亿题(七)

文章目录一题目二.思路2.1链表2.2数组三.代码一题目 原题传送门&#xff1a;力扣 题目&#xff1a; 题目的意思是让你写一个数据结构&#xff0c;这个结构的特点和队列一样先进先出&#xff0c;然后完成&#xff1a;判断是否为空&#xff0c;判断是否为满&#xff0c;添加一个…

实验29:循迹传感器实验

今天讲一个基本实验 循迹实验 循迹传感器的原理是: CTRT5000传感器的红外发射管不断发射红外光。由于黑色吸收光线,当红外发射管照射黑色表面时,反射光较少,接收管接收的红外线较少。这表明黑色吸收光线的强度大,那么比较器输出高电平,指示灯熄灭。同样,当它在白色表面…

MCE虚拟筛选化合物库

Discovery Diversity Sets 新颖的化合物库&#xff01; 药物筛选是发现药物先导物的重要途径&#xff0c;好的化合物库则是药物筛选的必备武器。MCE 拥有丰富的数据库资源&#xff0c;助力您的药物筛选研究&#xff01;药物筛选研究与化合物新颖性密切相关。Discovery Divers…

单目标应用:求解旅行商问题(TSP)的猎豹优化算法(The Cheetah Optimizer,CO)提供MATLAB代码

一、猎豹优化算法 猎豹优化算法&#xff08;The Cheetah Optimizer&#xff0c;CO&#xff09;由MohammadAminAkbari等人于2022年提出&#xff0c;该算法性能高效&#xff0c;思路新颖。 参考文献&#xff1a; Akbari, M.A., Zare, M., Azizipanah-abarghooee, R. et al. The…

Linux实战案例——使用LNMP+WordPress搭建个人博客网站

一、案例目标 了解 LNMP 环境的组成。 了解 LNMP 环境的部署与安装。 了解 WordPress 应用的部署与使用二、环境介绍 1.LNMP LNMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写。L指Linux&#xff0c;N指Nginx&#xff0c;M一般指MySQL&#xff0c;也…

技术分享 | TiUP工具 - TiDB集群滚动升级核心流程解析

作者&#xff1a;贲绍华 爱可生研发中心工程师&#xff0c;负责项目的需求与维护工作。其他身份&#xff1a;柯基铲屎官。 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 引言&#xff1a…

运维工程师怎么找兼职?什么样的兼职合适?

运维老哥们应该都知道&#xff0c;这个岗位其实是个很宽泛的定义&#xff0c;不同公司对运维的要求也不一样。有些公司所谓运维就是桌面helpdesk ,有些公司就是网管。基本上从修电脑到会写点脚本做自动化&#xff0c;各个层次的都有。现状就是&#xff0c;有少数公司或者大厂的…

基于Django的图书交易系统

摘 要 随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;图书交易系统也不例外&#xff0c;但目前国内的有些公司仍然都使用人工管理&#xff0c;图书销量越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化…

第五课 算术运算

一、加法与减法 经过上次课的学习&#xff0c;我们已经学会了该如何在控制台中输出我们想要的内容了&#xff0c;但是计算机计算机&#xff0c;最早其实是用来进行计算的&#xff0c;Python能做这事吗&#xff0c;我们来试试。 看到这结果&#xff0c;估计很多同学就该说了&…

【每周研报复现】基于阻力支撑相对强度(RSRS)的市场择时

原创文章第106篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑&#xff0c; AI量化投资”。 今天要复现的研报是&#xff1a;”光大证券_金融工程深度&#xff1a;基于阻力支撑相对强度&#xff08;RSRS&#xff09;的市场择时——技术择时系列报告之一“。 研报核心…

写个注解帮你净化使用分布式锁的重复操作

RedissonAop实现分布式锁 前言 简介 Aop的意义 AOP 旨在从业务逻辑中分离出来通用逻辑&#xff0c;切面实现了跨越多种类型和对象的关注点&#xff08;例如事务管理、日志记录、权限控制&#xff09;的模块化。 例子 就以这段代码为例子&#xff0c;这段代码总是回去获取锁之…

【HTML】关于height值设置和显示不同的原因以及font-size对象为中文和英文的区别

关于height值设置和显示不同的原因 height: 100px; CSS中把高度设置为100px&#xff0c;但是实际测量发现高度为125px 这个是因为&#xff1a;笔记本默认显示大小为125%&#xff0c;所以100的125%就是125. 还有一点&#xff0c;在你写网页时&#xff0c;要注意网页的缩放一定…

050_阵列天线方向图乘积原理

天线增益概念。原创不易&#xff0c;恐有错误&#xff0c;恳请读者指正。碎片三分钟逛电巢App&#xff0c;收获一丢丢。 天线定向性(directivity) 假设理想的无定向性天线&#xff0c;在远场区的3D球面空间各方向的辐射功率都相等&#xff0c;则定义球面等辐射功率的方向图的定…

Linux内存泄露案例分析和内存管理分享

作者&#xff1a;李遵举 一、问题 近期我们运维同事接到线上LB&#xff08;负载均衡&#xff09;服务内存报警&#xff0c;运维同事反馈说LB集群有部分机器的内存使用率超过80%&#xff0c;有的甚至超过90%&#xff0c;而且内存使用率还再不停的增长。接到内存报警的消息&…

代码随想录day56|583. 两个字符串的删除操作|72. 编辑距离|编辑距离总结篇|Golang

代码随想录day56 考试周了解一下 目录 代码随想录day56 583. 两个字符串的删除操作 72. 编辑距离 动态规划之编辑距离总结篇 583. 两个字符串的删除操作 思路 动态规划一 本题和动态规划&#xff1a;115.不同的子序列相比&#xff0c;其实就是两个字符串都可以删除了&am…

2023职教高考报名开启,报考人数继续增加

进入11月起&#xff0c;各地区2023年职教高考报名已经陆续开始&#xff0c;报考考生主要以中职学校学生为主。根据南京日报的报道&#xff0c;11月1日就启动的江苏省职教高考报名&#xff0c;吸引了不少家长和学生的关注&#xff0c;有些专业的报名人数已经比2022年翻了不止一倍…

Flutter Hooks — 快速了解

Flutter Hooks — 快速了解 前言 Hooks,直译过来就是"钩子"&#xff0c;是前端 React 框架加入的特性&#xff0c;用来分离状态逻辑和视图逻辑。现在这个特性并不只局限在于 React 框架中&#xff0c;其它前端框架也在借鉴。 我们都知道在 FLutter 开发中的一大痛点就…

图解 | 监控系统 Prometheus 的原理

本篇将会以图解的方式剖析 Prometheus 的原理。本文主要内容如下&#xff1a; 一、Prometheus 是什么&#xff1f; ELK Stack 日志收集和检索平台想必大家应该比较熟悉&#xff0c;Elasticsearch Filebeat Logstash Kibana。 ELK 架构 而 Prometheus 就相当于一整个 ELK&a…

功率放大器的主要指标有哪些呢

功率放大器是电子测量行业比较常见的能够放大信号源电压信号的仪器&#xff0c;虽然功率放大器的应用十分广泛&#xff0c;但是很多人对于功率放大器的主要指标参数还不了解&#xff0c;就让安泰电子来为大家介绍功率放大器的主要指标。 功率放大器的核心参数指标包括带宽、电压…

python多线程返回值问题重写Thread类的run方法

python多线程使用 文章目录python多线程使用一、案例二、说明1、针对第一种是有返回值的 &#xff0c;可以通过future.result() 去拿到每个线程返回值2、无返回值问题3、我们可以重写这个Thread类重写了__init__、run方法和join方法&#xff0c;主要是start()涉及的方法太多了而…