OSS(对象存储)

什么是OSS?

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

OSS具有与平台无关的RESTful API接口,您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

您可以使用阿里云提供的API、SDK包或者OSS迁移工具轻松地将海量数据移入或移出阿里云OSS。数据存储到阿里云OSS以后,您可以选择标准存储(Standard)作为移动应用、大型网站、图片分享或热点音视频的主要存储方式,也可以选择成本更低、存储期限更长的低频访问存储(Infrequent Access)、归档存储(Archive)、冷归档存储(Cold Archive)或者深度冷归档(Deep Cold Archive)作为不经常访问数据的存储方式。

什么是对象存储?

在如今这个数据爆炸的时代,高效、灵活的数据存储解决方案显得尤为重要。对象存储(Object Storage)是一种存储架构,它以对象为单位来处理、存储和检索数据。与传统的文件存储和块存储不同,对象存储将数据作为对象进行管理,每个对象都包含了数据本身、元数据以及一个全局唯一的标识符。这种独特的存储方式使得对象存储在处理大量、非结构化的数据时具有明显的优势。

对象存储通过API(应用程序编程接口)调用进行数据的读写,通常基于HTTP或HTTPS协议。对象存储系统将数据分布在多个硬件设备上,并且能够自动处理数据的冗余备份和扩展性问题,这使得它在大规模数据存储方面表现出色。

对象存储的优势是什么?

  • 可扩展性

    对象存储系统非常适合云环境,能够轻松地横向扩展以适应数据增长。由于数据是作为单独的对象进行管理,所以可以在不同的物理设备上无缝地分布这些对象,从而实现几乎无限的扩展。这使得对象存储非常适合存储大量非结构化数据,例如图片、视频和日志文件。

  • 数据持久性和可靠性

    对象存储系统通常将数据复制到多个服务器和地理位置,以确保数据的持久性和高可用性。这意味着即使发生硬件故障或其他类型的系统故障,数据仍然可以安全地恢复。此外,一些对象存储系统提供数据版本控制,这有助于防止数据丢失或覆盖。

  • 成本效率

    对象存储通常基于使用量付费的模型,使用户能够根据实际需求进行付费,而不用提前投资大量的存储设备。此外,由于其良好的可扩展性,用户可以根据需要逐渐增加存储容量,而无需过度投资。这样可以降低总体拥有成本(TCO)和运营成本。对象存储为云原生应用、数据湖、大数据分析、日志记录和机器学习等场景提供了一种低成本、高效益的方式来存储海量数据。

  • 数据可访问性和共享

    对象存储系统可以通过标准的HTTP/HTTPS协议访问,这意味着对象可以直接通过Web进行存储、检索和共享。这种方式简化了远程访问,使得数据共享和协作更加容易,尤其是对于分布在全球的团队和应用程序。

  • 简化管理

    由于对象存储系统通常使用扁平的命名空间而不是传统的文件系统层次结构,管理海量数据变得更加简单。无需处理复杂的文件系统限制,如文件夹大小或文件数目限制。用户可以通过简单的API调用来存储和检索数据,这使得集成和自动化更加容易。

创建OSS

阿里对象存储可免费使用三个月

创建Bucket

存储空间(Bucket)是存放文件的容器,开始使用OSS前,需要先创建一个Bucket。

  1. 在左侧导航栏进入Bucket列表页面,单击创建Bucket

  2. 配置以下关键参数,其余保留默认值:

    • Bucket名称 :输入一个全局唯一的名称,为确保唯一,建议使用项目名-地域-随机字符串 的组合,例如my-project-hangzhou-a1b2c3d4

    • 地域:选择距离您较近的地域,例如华东1(杭州),以降低访问延迟。

  3. 单击完成创建

使用官方SDK在Java服务端创建Bucket

我这边使用Spring Boot来创建桶

引入依赖

复制代码
<dependencies>
       <dependency>
           <groupId>com.aliyun.oss</groupId>
           <artifactId>aliyun-sdk-oss</artifactId>
           <version>3.17.4</version>
       </dependency>

       <!-- Lombok:简化POJO类编写,提供@Data/@Getter/@Setter等注解 -->
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>1.18.30</version>
           <scope>provided</scope>
       </dependency>

       <!-- SpringBoot 核心依赖 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter</artifactId>
           <version>2.7.18</version> <!-- 选稳定版本即可 -->
       </dependency>
       <!-- Lombok 依赖(已有则无需重复引入) -->
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>1.18.30</version>
           <scope>provided</scope>
       </dependency>

       <!-- Spring Boot Web 核心依赖,包含 @RequestMapping 所需的所有类 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
            <version>2.7.18</version>
       </dependency>
   </dependencies>

官方推荐在本地cmd运行

setx OSS_ACCESS_KEY_ID "YOUR_ACCESS_KEY_ID"

setx OSS_ACCESS_KEY_SECRET "YOUR_ACCESS_KEY_SECRET"

这样只能在本地使用

可以推荐写在yaml文件中

配置文件

复制代码
# application.yml
aliyun:
  oss:
    # OSS 服务端点(根据你的 Bucket 地域修改,比如杭州是 oss-cn-hangzhou.aliyuncs.com)
    endpoint: https://oss-cn-beijing.aliyuncs.com
    # 你的 AccessKey ID
    access-key-id: LTAI5tEwS94XXZS8SxZRBDie
    # 你的 AccessKey Secret
    access-key-secret: GzaCUuKs6mQiCg6zGqpZSiDdsLk6vU
    # 要创建的 Bucket 名称(需全局唯一)
    bucket-name: hhj-xian-hhj25802580

    region: cn-beijing

接收配置

然后使用vo类来接收

复制代码
package osstest.vo;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component  // 加上 @Component 或者 @Configuration,使其成为 Spring Bean
@ConfigurationProperties(prefix = "aliyun.oss")  // 自动绑定 application.yml 配置
public class OssRequest {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    private String region;
}

接口层逻辑

在接口层使用Spring容器将OssRequest依赖引入controller

复制代码
@Autowired
private OssRequest ossRequest;

根据阿里云官方SDK,来进行创建Bucket,下面是完整代码

复制代码
@RestController
@RequestMapping("/oss")
public class OssController {

    @Autowired
    private OssRequest ossRequest;

    public String generateUniqueBucketName(String prefix) {
        // 获取当前时间戳
        String timestamp = String.valueOf(System.currentTimeMillis());
        // 生成一个 0 到 9999 之间的随机数
        Random random = new Random();
        int randomNum = random.nextInt(10000); // 生成一个 0 到 9999 之间的随机数
        // 连接以形成一个唯一的 Bucket 名称
        return prefix + "-" + timestamp + "-" + randomNum;
    }


    @RequestMapping("/run")
    public String ossRun() {

        // 从配置里获取配置
        String endpoint = ossRequest.getEndpoint();
        String region = ossRequest.getRegion();
        String accessKeyId = ossRequest.getAccessKeyId();
        String accessKeySecret = ossRequest.getAccessKeySecret();

        String bucketName = generateUniqueBucketName("demo");

        // 创建 OSS Client
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSignatureVersion(SignVersion.V4);

        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(
                        new DefaultCredentialProvider(accessKeyId, accessKeySecret)
                )
                .region(region)
                .clientConfiguration(conf)
                .build();

        try {
            // 1. 创建 Bucket
            ossClient.createBucket(bucketName);
            System.out.println("1. Bucket 创建成功:" + bucketName);

            // 2. 上传文件
            String objectName = "exampledir/exampleobject.txt";
            String content = "Hello OSS";
            ossClient.putObject(
                    bucketName,
                    objectName,
                    new ByteArrayInputStream(content.getBytes())
            );
            System.out.println("2. 文件上传成功");

            // 3. 下载文件
            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(ossObject.getObjectContent())
            );
            String line;
            System.out.println("3. 下载的文件内容:");
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();

            // 4. 列出文件
            System.out.println("4. Bucket 文件列表:");
            ObjectListing objectListing = ossClient.listObjects(bucketName);
            for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
                System.out.println(" - " + s.getKey() + " (size=" + s.getSize() + ")");
            }

            // 5. 删除文件
            ossClient.deleteObject(bucketName, objectName);
            System.out.println("5. 文件删除成功");

            // 6. 删除 Bucket
            ossClient.deleteBucket(bucketName);
            System.out.println("6. Bucket 删除成功");

            return "OSS 操作成功!";
        } catch (OSSException | ClientException | IOException e) {
            e.printStackTrace();
            return "OSS 操作失败:" + e.getMessage();
        } finally {
            ossClient.shutdown();
        }
    }
}

运行接口

http://localhost:8080/oss/run

出现这个则运行成功,但是Bucket被删除掉了,看不到云存储的Bucket,可以将删除代码注释掉来验证

出现创建的Bucket

一般创建Bucket直接在阿里云控制台创建,可以修改配置

上传文件

上传文件可以理解为,将本地的文件例如:.pdf等,上传到对象存储

下面我依然用接口写上传文件操作

注意:上传的文件超过默认上传文件大小会报错所以可以先将文件配置改大

配置文件限制大小

复制代码
spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

文件上传接口

接下来进行上传文件

复制代码
 // 上传文件
    @RequestMapping("/upload")
    public String ossUpload(@RequestParam("url") MultipartFile url) {
        String inputStream = url.getOriginalFilename();
        assert inputStream != null;

        // 从配置里获取配置
        String endpoint = ossRequest.getEndpoint();
        String region = ossRequest.getRegion();
        String accessKeyId = ossRequest.getAccessKeyId();
        String accessKeySecret = ossRequest.getAccessKeySecret();
        String bucketName = ossRequest.getBucketName();
        String objectName = "exampledir/"+System.currentTimeMillis() +"/"+inputStream;


        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(
                        new DefaultCredentialProvider(accessKeyId, accessKeySecret)
                )
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            InputStream inputSm = url.getInputStream();
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType("application/pdf");
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName,inputSm);
            putObjectRequest.setMetadata(metadata);
             //如果需要上传时设置存储类型和访问权限,请参考以下示例代码。

            // 上传文件。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            return "OSS成功";
        } 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 (IOException e) {
            throw new RuntimeException(e);
        } finally {
            ossClient.shutdown();
        }
        return "失败";
    }
复制代码
objectName:"exampledir/"+System.currentTimeMillis() +"/"+inputStream;

exampledir在对象存储上的路径文件夹,System.currentTimeMillis():官方给的objectname的文件名是常量值为了避免创建的文件名称相同,我是用当前时间来区别,但是后面我写的inputStream来取上传的文件名称作为对象存储的文件名称

可以用postman测试接口运行情况

运行成功可以去oss上进行验证

接下来运行成功,OSS Bucket域名访问HTML、图片等文件时,浏览器会强制下载而非在线预览,影响用户体验。通过将自定义域名绑定至Bucket,可以使用自定义域名替代OSS Bucket域名直接访问文件,实现在线预览,并获得更灵活的访问控制能力。

相关推荐
工业甲酰苯胺2 小时前
spring-事务管理
数据库·sql·spring
落花流水 丶2 小时前
Spring Security 完全指南
java·spring
爱敲代码的小鱼5 小时前
web后端开发SpringBootWeb的入门:
java·spring boot·spring
那我掉的头发算什么6 小时前
【SpringBoot】统一功能处理详解
java·spring boot·后端·spring
rlpp6 小时前
spring.profiles.active和spring.profiles.include的使用及区别说明
java·后端·spring
MX_93599 小时前
Spring xml 方式整合第三方框架总结加案例
xml·java·spring
该叫啥9 小时前
Spring Bean 生命周期
java·spring·servlet
androidstarjack10 小时前
2026 年 IM 即时通讯方案选型实践:4 家主流厂商对比分析
java·spring·spring cloud
、BeYourself10 小时前
Spring AI 文档切片策略优化指南
java·人工智能·spring