阿里云OSS文件存储

news2024/11/13 15:00:55

文章目录

    • 参考
    • 准备
      • 创建bucket
      • endpoint 和 bucket域名的访问路径
      • AccessKey和OSS的开发文档
    • Springboot整合OSS
      • 引入依赖
      • AliyunOssConfig
      • AliyunOssProperties
      • applicatioin.yml
      • 简单上传和下载
      • 使用签名URL进行临时授权访问
      • 生成以PUT方法访问的签名URL来上传文件
      • 通过签名URL临时授权简单上传文件
      • 使用签名URL临时授权下载文件
      • 服务端签名直传

参考

阿里云java的sdk官方示例代码

前端不暴露ak/sk直接上传阿里云oss的方案

前端直传阿里云OSS

阿里云 OSS 客户端直传 Policy 模式使用
服务端签名直传并设置上传回调官方文档Java

使用阿里云STS临时token完成阿里云OSS图片上传(Springboot+Vue)
使用STS临时访问凭证通过客户端直连OSS对象存储服务器
使用STS临时访问凭证访问OSS-官方文档
阿里云OSS STS最佳实践,看这一篇就够了
前端通过STS方式直传至阿里云OSS(包含文件上传、下载和自动刷新stsToken)

准备

创建bucket

在这里插入图片描述

endpoint 和 bucket域名的访问路径

endpoint 和 bucket域名的访问路径
在这里插入图片描述

AccessKey和OSS的开发文档

创建AccessKey(图中点击进去即可创建)和查看OSS的开发文档
在这里插入图片描述
开发文档
在这里插入图片描述
AccessKey在这里插入图片描述

Springboot整合OSS

引入依赖

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

AliyunOssConfig

@EnableConfigurationProperties(AliyunOssProperties.class)
@Component
public class AliyunOssConfig {

    @Autowired
    private AliyunOssProperties aliyunOssProperties;

    @Bean
    public OSS ossClient() {
        OSS oss = new OSSClientBuilder().build(
                aliyunOssProperties.getEndpoint(),
                aliyunOssProperties.getAccessKeyId(),
                aliyunOssProperties.getSecretAccessKey()
        );
        return oss;
    }

}

AliyunOssProperties

@Data
@ConfigurationProperties(prefix = "oss")
public class AliyunOssProperties {

    private String endpoint;

    private String accessKeyId;

    private String secretAccessKey;

    // 上传到哪个桶
    private String bucketName;

    // 上传的桶中的文件的访问域名
    private String bucketDomain;

}

applicatioin.yml

oss:
  accessKeyId: ~~~
  secretAccessKey: ~~~
  endpoint: https://oss-cn-shenzhen.aliyuncs.com
  bucketName: zzhua-oss-bucket2
  bucketDomain: https://${oss.bucketName}.oss-cn-shenzhen.aliyuncs.com

简单上传和下载

@SpringBootTest(classes = MinioApp.class)
public class TestOssApp {

    @Autowired
    private OSSClient ossClient;

    @Autowired
    private AliyunOssProperties aliyunOssProperties;

    // 流式上传
    @Test
    void testStreamUpload() throws Exception {

        String filePath= "C:\\Users\\zzhua195\\Desktop\\soft-dev.png";
        File file = new File(filePath);
        InputStream inputStream = new FileInputStream(file);

        String objectName = file.getName();
        // 创建PutObjectRequest对象。
        PutObjectRequest putObjectRequest = new PutObjectRequest(
                aliyunOssProperties.getBucketName(),
                objectName,
                inputStream
        );


        // 创建PutObject请求。
        PutObjectResult result = ossClient.putObject(putObjectRequest);

        System.out.println(file.getName());

        // 注意需要关闭 阻止公共访问, 读写权限改为公共读
        // 如: https://zzhua-oss-bucket2.oss-cn-shenzhen.aliyuncs.com/soft-dev.png
        System.out.println("访问路径为: " + aliyunOssProperties.getBucketDomain() + "/" + objectName);

    }

    // 流式下载
    @Test
    void testStreamDownload() throws Exception {
        String filePath= "C:\\Users\\zzhua195\\Desktop\\soft-dev1111.png";
        File file = new File(filePath);

        try {
            OSSObject ossObject = null;
            ossObject = ossClient.getObject(aliyunOssProperties.getBucketName(), "soft-dev.png");

            FileOutputStream fos = new FileOutputStream(file);
            StreamUtils.copy(ossObject.getObjectContent(), fos);
            fos.close();
        } catch (Exception e) {
            System.out.println("获取资源失败");
        }

    }
}

使用签名URL进行临时授权访问

bucket开启阻止公共访问, 读写权限设置为私有, 此时直接使用{bucketDomain}/{objectName}无法直接访问资源。此时,需要生成1个url, 并且携带签名信息才能访问

@Test
void testGeneratedSignedUrl() {

    String objectName = "20240825/soft-dev.png";

    GeneratePresignedUrlRequest generatePresignedUrlReq = new GeneratePresignedUrlRequest(
            aliyunOssProperties.getBucketName(),
            objectName,
            HttpMethod.GET
    );
    // 必须设置有效时间
    generatePresignedUrlReq.setExpiration(new Date(new Date().getTime() + 3 * 60 * 1000L));
    
    URL url = ossClient.generatePresignedUrl(generatePresignedUrlReq);
    
    // 示例: https://zzhua-oss-bucket.oss-cn-shenzhen.aliyuncs.com/20240825/soft-dev.png?Expires=1724635526&OSSAccessKeyId=LTAI5tDVake7ZcZrwbCDjP97&Signature=3BT%2BCJPRx3YDxOxRS8qtVhTHJHI%3D
    System.out.println(url.toString());

}

生成以PUT方法访问的签名URL来上传文件

@Test
void testGenrateSignedPut() throws Exception {

    GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(
            aliyunOssProperties.getBucketName(),
            "naughty.gif",
            HttpMethod.PUT
    );

    // 设置签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
    Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
    request.setExpiration(expiration);
    // 设置ContentType。
    request.setContentType("image/gif");
    // 设置自定义元数据。
    request.addUserMetadata("author", "zzhua");

    // 生成签名URL。
    URL signedUrl = ossClient.generatePresignedUrl(request);
    System.out.println(signedUrl);

    Map<String, String> requestHeaders = new HashMap<String, String>();
    // 设置ContentType,必须和生成签名URL时设置的ContentType一致。
    requestHeaders.put(HttpHeaders.CONTENT_TYPE, "image/gif");
    // 设置自定义元数据。
    requestHeaders.put(OSS_USER_METADATA_PREFIX + "author", "zzhua");

    FileInputStream inputStream = new FileInputStream("C:\\Users\\zzhua195\\Desktop\\naughty.gif");

    // 使用签名URL上传文件。
    PutObjectResult putObjectResult = ossClient.putObject(signedUrl, inputStream, -1, requestHeaders, true);

}

通过签名URL临时授权简单上传文件

使用下面代码可以先生成1个上传的签名url,然后使用这个url来put上传文件(但是在postman中就是上传失败,报SignatureDoesNotMatch错误)

@Test
void testGenratePutSimpleUpload() throws Exception {

    // 设置请求头。
    Map<String, String> headers = new HashMap<String, String>();
    /*// 指定Object的存储类型。
    headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
    // 指定ContentType。
    headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/

    // 设置用户自定义元数据。
    Map<String, String> userMetadata = new HashMap<String, String>();
    /*userMetadata.put("key1","value1");
    userMetadata.put("key2","value2");*/

    URL signedUrl = null;
    try {
        // 指定生成的签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
        Date expiration = new Date(new Date().getTime() + 3600 * 1000L);

        // 生成签名URL。
        String objectName = "naughty.gif";
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(
                aliyunOssProperties.getBucketName(),
                objectName,
                HttpMethod.PUT
        );
        // 设置过期时间。
        request.setExpiration(expiration);

        // 将请求头加入到request中。
        request.setHeaders(headers);
        // 添加用户自定义元数据。
        request.setUserMetadata(userMetadata);

        // 通过HTTP PUT请求生成签名URL。
        signedUrl = ossClient.generatePresignedUrl(request);
        // 打印签名URL。
        System.out.println("signed url for putObject: " + signedUrl);

    } catch (OSSException oe) {
        System.out.println("生成失败~~~");
    }

    if (1 > 0) {
        return;
    }

    // 使用生成的签名url来上传文件
    CloseableHttpClient httpClient = null;
    CloseableHttpResponse response = null;
    try {
        HttpPut put = new HttpPut(signedUrl.toString());
        HttpEntity entity = new FileEntity(new File("C:\\Users\\zzhua195\\Desktop\\naughty.gif"));
        put.setEntity(entity);
        // 如果生成签名URL时设置了header参数,例如用户元数据,存储类型等,则调用签名URL上传文件时,也需要将这些参数发送至服务端。如果签名和发送至服务端的不一致,会报签名错误。
        for(Map.Entry header: headers.entrySet()){
            put.addHeader(header.getKey().toString(),header.getValue().toString());
        }
        for(Map.Entry meta: userMetadata.entrySet()){
            // 如果使用userMeta,sdk内部会为userMeta拼接"x-oss-meta-"前缀。当您使用其他方式生成签名URL进行上传时,userMeta也需要拼接"x-oss-meta-"前缀。
            put.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString());
        }

        httpClient = HttpClients.createDefault();

        response = httpClient.execute(put);

        System.out.println("返回上传状态码:"+response.getStatusLine().getStatusCode());
        if(response.getStatusLine().getStatusCode() == 200){
            System.out.println("使用网络库上传成功");
        }
        System.out.println(response.toString());
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        response.close();
        httpClient.close();
    }
}

使用签名URL临时授权下载文件

跟使用签名URL进行临时授权访问是一样的

@Test
void testGenerateDownload() throws IOException {
    // 设置请求头。
    Map<String, String> headers = new HashMap<String, String>();
    /*// 指定Object的存储类型。
    headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
    // 指定ContentType。
    headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/

    // 设置用户自定义元数据。
    Map<String, String> userMetadata = new HashMap<String, String>();
    /*userMetadata.put("key1","value1");
    userMetadata.put("key2","value2");*/

    URL signedUrl = null;
    try {
        // 指定生成的签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
        Date expiration = new Date(new Date().getTime() + 3600 * 1000L);

        // 生成签名URL。
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(
                aliyunOssProperties.getBucketName(),
                "20240825/soft-dev.png",
                HttpMethod.GET
        );
        // 设置过期时间。
        request.setExpiration(expiration);

        // 将请求头加入到request中。
        request.setHeaders(headers);
        // 添加用户自定义元数据。
        request.setUserMetadata(userMetadata);

        // 设置查询参数。
        // Map<String, String> queryParam = new HashMap<String, String>();
        // 指定IP地址或者IP地址段,对应日志中sourceIpFromSource的值。
        // queryParam.put("x-oss-ac-source-ip","192.0.2.0");
        // 将子网掩码转换为二进制,然后填写转换结果中1的数量。
        // queryParam.put("x-oss-ac-subnet-mask","32");
        // 指定VPC ID。
        // queryParam.put("x-oss-ac-vpc-id","vpc-12345678");
        // 指定是否允许转发请求。
        // queryParam.put("x-oss-ac-forward-allow","true");
        // request.setQueryParameter(queryParam);

        // 设置单链接限速,单位为bit,例如限速100 KB/s。
        // request.setTrafficLimit(100 * 1024 * 8);

        // 通过HTTP GET请求生成签名URL。
        signedUrl = ossClient.generatePresignedUrl(request);

        // 打印签名URL。
        System.out.println("signed url for putObject: " + signedUrl);

    } catch (Exception e) {
        System.out.println("发生错误" + e);
    }

    // 通过签名URL下载文件,以HttpClients为例说明。
    CloseableHttpClient httpClient = null;
    CloseableHttpResponse response = null;
    try {
        HttpGet get = new HttpGet(signedUrl.toString());

        // 如果生成签名URL时设置了header参数,例如用户元数据,存储类型等,则调用签名URL下载文件时,也需要将这些参数发送至服务端。如果签名和发送至服务端的不一致,会报签名错误。
        for(Map.Entry header: headers.entrySet()){
            get.addHeader(header.getKey().toString(),header.getValue().toString());
        }
        for(Map.Entry meta: userMetadata.entrySet()){
            // 如果使用userMeta,sdk内部会为userMeta拼接"x-oss-meta-"前缀。当您使用其他方式生成签名URL进行下载时,userMeta也需要拼接"x-oss-meta-"前缀。
            get.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString());
        }

        httpClient = HttpClients.createDefault();
        response = httpClient.execute(get);

        System.out.println("返回下载状态码:"+response.getStatusLine().getStatusCode());
        if(response.getStatusLine().getStatusCode() == 200){
            System.out.println("使用网络库下载成功");
        }
        System.out.println(response.toString());

        // 保存文件到磁盘。
        DataInputStream in = null;
        OutputStream out = null;
        try {
            in = new DataInputStream(response.getEntity().getContent());


            String pathName = "C:\\Users\\zzhua195\\Desktop\\ttt.png";
            out = new DataOutputStream(new FileOutputStream(pathName));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            in.close();
            out.close();
        }
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        response.close();
        httpClient.close();
    }
}

服务端签名直传

在这里插入图片描述

@GetMapping("/getPolicy")
public JSONObject getPolicy() throws Exception {
    // host的格式为 bucketname.endpoint
    // String host = StringFormatter.concat("https://", bucketName, ".", endpoint).getValue();
    String host = aliyunOssProperties.getBucketDomain();
    // callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
    // String callbackUrl = "http://88.88.88.88:8888";
    // 每一天产生一个文件夹
    String dir = LocalDate.now().toString() + "/"; // 用户上传文件时指定的前缀,如果是 / 则自动检测为文件夹。

    JSONObject jsonObject = new JSONObject();

    long expireTime = 600;
    long expireEndTime = System.currentTimeMillis() + expireTime * 1000; //过期时间 100 秒
    Date expiration = new Date(expireEndTime);

    // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
    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);

    jsonObject.put("OSSAccessKeyId", aliyunOssProperties.getAccessKeyId());
    jsonObject.put("policy", encodedPolicy);
    jsonObject.put("signature", postSignature);
    jsonObject.put("dir", dir);
    jsonObject.put("host", host);
    jsonObject.put("expire", String.valueOf(expireEndTime / 1000));
    return jsonObject;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

WIFI 配网

配网:指的是外部向WiFi模块提供SSID和密码&#xff0c;以便Wi-Fi模块可以连接指定的热点 常见的配网方式有:-键配网smart config、SoftAP配网、蓝牙配网、屏幕配网。 1.0 一键配网 2.0 蓝牙配网 一键配网的模式对应的厂加模式 3.0 状态机WIFI模组物联网 4.0 创建枚举结构体 ty…

女性权益之镜:印度侵害事件分析

1.项目背景 近年来&#xff0c;印度社会关于女性权利的讨论日益频繁&#xff0c;然而&#xff0c;女性受侵害的违法事件仍层出不穷&#xff0c;这些事件不仅威胁到女性的生命安全&#xff0c;还深刻影响了社会的稳定与发展&#xff0c;尽管印度政府在法律和政策层面采取了一系…

实现并发网络服务器

一&#xff0c;网络服务器 1.单循环网络服务器 —— 同一时刻只能处理一个客户端任务 2.并发服务器 —— 同一时刻能处理多个客户端任务 二&#xff0c;并发服务器 1.多线程 2.IO多路复用 3.多进程 三&#xff0c;IO模型 1.阻塞IO 阻塞IO&#xff08;Blocking IO&…

IO进程day03(获取文件属性、目录操作、库Lib)

目录 【1】获取文件属性 1》stat函数 2》获取文件类型 3》获取文件权限 练习&#xff1a;编程实现“ls -l 文件名” 的功能 4》stat、fstat、lstat的区别 【2】目录操作 【3】库 Lib 1》文件分类 1> 头文件&#xff1a; 以 .h结尾的文件 2> 源文件&#xff1a…

Qt之控件介绍

目录 控件概述 QWidget核心属性 1.enabled属性 2.geometry属性 3.windowTitle属性 4.windowIcon属性 5.windowOpacity属性 6.cursor属性 7.font属性 8.toolTip属性 9.focusPolicy属性 10.styleSheet属性 按钮类控件&#xff1a; 1.PushButton 2.RadioBu…

Leetcode 17. 电话号码的字母组合 C++实现

Leetcode 17. 电话号码的字母组合 问题&#xff1a;给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 算法&#xff1a;递归嵌…

PyTorch深度学习模型训练流程:(二、回归)

回归的流程与分类基本一致&#xff0c;只需要把评估指标改动一下就行。回归输出的是损失曲线、R^2曲线、训练集预测值与真实值折线图、测试集预测值散点图与真实值折线图。输出效果如下&#xff1a; 注意&#xff1a;预测值与真实值图像处理为按真实值排序&#xff0c;图中呈现…

机器学习概述与应用:深度学习、人工智能与经典学习方法

引言 机器学习(Machine Learning)是人工智能(AI)领域中最为核心的分支之一,其主要目的是通过数据学习和构建模型,帮助计算机系统自动完成特定任务。随着深度学习(Deep Learning)的崛起,机器学习技术在各行各业中的应用变得越来越广泛。在本文中,我们将详细介绍机器学…

Datawhale X 李宏毅苹果书 AI夏令营 Task1笔记

课程内容 学习笔记 &#xff08;一&#xff09;术语解释 一 . 机器学习&#xff08;Machine Learning&#xff0c;ML&#xff09; 机器学习&#xff0c;在本书的解释中是让机器具备找一个函数的能力。个人理解是基于所拥有的数据构建起概率统计模型来对数据进行预测与分析。…

python可视化-散点图

散点图可以了解数据之间的各种相关性&#xff0c;如正比、反比、无相关、线性、指数级、 U形等&#xff0c;而且也可以通过数据点的密度&#xff08;辅助拟合趋势线&#xff09;来确定相关性的强度。另外&#xff0c;也可以探索出异常值&#xff08;在远超出一般聚集区域的数据…

【Java】Record的使用 (简洁教程)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述四、解决方案&#xff1a;4.1 为什么引入Record4.2 Record与Class区别4.3 使用场景 五、总结&#xff1a;…

使用uni-app开发微信小程序

一、前提环境 1.1 &#xff1a;uniapp开发文档&#xff1a;https://uniapp.dcloud.net.cn/quickstart-cli.html 细节都在这一页&#xff0c;这里不过多解释 二、开发工具下载 2.1 微信开发者工具 下载链接&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/dev…

Java:Calendar类

文章目录 Calendar类常用方法代码 黑马学习笔记 Calendar类 calendar是可变对象&#xff0c;一旦修改后其对象本身表示的时间将发生变化 原始对象会跟着修改&#xff0c;造成原始对象的丢失 常用方法 代码 package Time;import java.util.Calendar; import java.util.Date;/…

【RabbitMQ高级特性】消息可靠性原理

1. 消息确认机制 1.1 介绍 我们可以看到RabbitMQ的消息流转图&#xff1a; 当消息从Broker投递给消费者的时候会存在以下两种情况&#xff1a; consumer消费消息成功consumer消费消息异常 如果说RabbitMQ在每次将消息投递给消费者的时候就将消息从Broker中删除&#xff0c…

用 like concat 不用 like,为了防止sql注入;#{}和${}的区别和用法;#{}预防SQL注入的原理

一、like concat 和 like mybatis中为了防止sql注入&#xff0c;使用like语句时并不是直接使用&#xff0c;而是使用concat函数<if test"goodName ! null and goodName ! "> and good_name like concat(%, #{goodName}, %)</if> concat()函数1、功能&a…

Webbench1.5安装使用Ubuntu

1、安装依赖包 sudo apt-get update sudo apt-get install libtirpc-dev2、安装Webbench1.5 参考https://github.com/baiguo/webbench-1.5 # 可能需要root权限&#xff0c;我是切换到root用户才安装成功 wget http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.…

APP.vue引入子组件进行页面展示

一.将vue项目启动服务器原始页面进行清空 打开APP.vue文件&#xff0c;将<template>标签里的内容和<style>标签里的内容 ctrl/ 选中进行注释&#xff0c;以及引入的Helloworld.vue文件内容代码进行注释 并且 ctrls 保存 服务器页面从原始页面 变为空白 二.在comp…

树莓派4B安装golang最新版(20210520)

前置条件&#xff1a; 树莓派4B 安装官方系统 Linux raspberrypi 5.10.17-v7l #1414 更换最新版的原因&#xff1a; 截至 2021.5.20 &#xff0c;Raspberry Pi OS 最新版系统中&#xff0c;默认安装golang1.11&#xff0c;但是使用 go get golang.org/x/crypto/ssh 时&#xff…

推荐系统实战(七)-多任务多场景(上)多任务

多任务Multi-Task&#xff0c;有时也被称为多目标Multi-Objective建模。比如说电商场景下&#xff0c;希望曝光的物料被多多点击&#xff0c;还希望商品被下单购买&#xff0c;因此同时建模三个目标&#xff1a;曝光到点击CTR&#xff0c;点击到购买转换率CVR&#xff0c;曝光到…

记一次对某佛教系统的漏洞挖掘

前言 简单记录一次漏洞挖掘&#xff0c;一个系统居然爆了这么多类型的洞&#xff0c;于是想记录哈。(比较基础&#xff0c;我是菜狗&#xff0c;大佬轻喷) 业务介绍 是一个某佛教的系统 有一些佛教的学习资源、一些佛教相关的实物商品可购买&#xff0c;有个人中心&#xff…