对象存储-OSS

目录

对象存储背景

阿里云OSS


对象存储背景

单节点环境下,文件往往存储在tomcat服务器内,随着业务需求的增多,单节点已不能满足需求,项目架构需要扩展到多节点(见下图),此时文件经过nginx转发存储到某一个节点,在分布式架构下对文件的访问就存在问题(文件存储到节点A,查看文件请求到节点B访问不了文件)。

在分布式环境下,需要引入集中管理文件的节点服务,改进如下:

分布式文件服务解决方案有很多,常见的有:独立搭建文件服务器,如基于开源FastDFS搭建;引入第三方云储存方案,如基于阿里云的OSS;相比独立搭建文件服务器,云存储方案有诸多优势:SDK使用简单、运维成本低、图形化的管理控制台、提供强大的文件处理功能、CDN加速、服务扩展简单等,本文重点讲述基于阿里云的OSS方案。

阿里云OSS

使用步骤如下:

1、【阿里云官网】开通OSS服务

2、【阿里云官网】创建Bucket

重点关注标签有:Bucket 名称、Endpoint,本文新建的Bucket 名称 = gingko-sawyer,Endpoint = oss-cn-beijing.aliyuncs.com

3、【阿里云官网】创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号,创建AccessKey,并将AccessKeyId和AccessKeySecret设置到本地电脑环境变量中。

4、后台编写代码实现基于阿里云OSS文件上传及下载

4.1、添加aliyun.oss依赖

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

4.2、修改配置,增加对oss的支持

复制代码
server:
  port: 8080
#aliyun oss config
aliyun:
  oss:
    endpoint: oss-cn-beijing.aliyuncs.com
    region: cn-beijing
    bucket-name: gingko-sawyer
    foler-prefix: oss/
    host: https://gingko-sawyer.oss-cn-beijing.aliyuncs.com

4.3 文件上传&下载程序

java 复制代码
package com.ginko.aliyunoss.controller;

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.Protocol;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.InputStream;

@RestController
@RequestMapping("oss")
@Slf4j
public class OSSController {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.region}")
    private String region;
    @Value("${aliyun.oss.bucket-name}")
    private String bucketName;
    @Value("${aliyun.oss.foler-prefix}")
    private String folerPrefix;//上传到oss中具体的文件夹目录
    @Value("${aliyun.oss.host}")
    private String host;

    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) throws Exception {

        // 创建 ClientBuilderConfiguration 实例,用于配置 OSS 客户端参数
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        // 设置签名算法版本为 V4
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        // 设置使用 HTTPS 协议访问 OSS,保证传输安全性
        clientBuilderConfiguration.setProtocol(Protocol.HTTPS);

        // 创建 OSS 客户端实例
        OSS ossClient = OSSClientBuilder.create()
                // endpoint
                .endpoint(this.endpoint)
                // 从环境变量中获取访问凭证(需提前配置 OSS_ACCESS_KEY_ID 和 OSS_ACCESS_KEY_SECRET)
                .credentialsProvider(CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider())
                // 设置客户端配置
                .clientConfiguration(clientBuilderConfiguration)
                // 设置region
                .region(this.region)
                .build();

        try {
            // 填写Bucket名称
            String bucketName = this.bucketName;
            // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
            String objectName = this.folerPrefix + file.getOriginalFilename();
            InputStream inputStream = file.getInputStream();
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            System.out.println(result);
        } finally {
            // 当OSSClient实例不再使用时,调用shutdown方法以释放资源
            ossClient.shutdown();
        }
        return "success";
    }


    @PostMapping("/download")
    public String download() throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = this.endpoint;
        //从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = this.bucketName;
        // 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。
        String objectName = this.folerPrefix + "1.png";
        // 填写Object下载到本地的完整路径。
        String pathName = "D:\\rename.png";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = this.region;

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

        try {
            // 下载Object到本地文件,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。
            // 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
            ObjectMetadata object = ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));

        } 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());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        return "success";
    }
}

5、测试,通过postman模拟上传及下载文件

如下图所示,1.png文件已经被上传到oss中,rename.png是从oss下载到本地的文件