【JavaWeb后端学习笔记】Java上传文件到阿里云对象存储服务

阿里云对象存储

  • 1、创建阿里云对象存储节点
  • 2、上传文件
    • [2.1 修改项目配置文件](#2.1 修改项目配置文件)
    • [2.2 定义一个Properties类获取配置信息](#2.2 定义一个Properties类获取配置信息)
    • [2.3 准备一个alioss工具类](#2.3 准备一个alioss工具类)
    • [2.4 创建注册类,将AliOssUtil 注册成Bean](#2.4 创建注册类,将AliOssUtil 注册成Bean)
    • [2.5 使用AliOssUtil 工具类上传文件](#2.5 使用AliOssUtil 工具类上传文件)
    • [2.6 注意事项](#2.6 注意事项)

使用阿里云对象存储服务分为以下几步:

1、创建阿里云对象存储节点

首先需要创建阿里云对象存储节点。获取endpoint、accessKeyId、accessKeySecret、bucketName四个信息。

  1. 进入阿里云官网,并注册登录。
  2. 鼠标悬放在产品上,然后悬放到存储上,然后点击对象存储OSS。
  3. 点击管理控制台。进入对象存储OSS管理控制台。
  4. 创建Bucket。如果是第一次使用对象存储OSS服务,则首先需要开通服务。开通后点击左上角Bucket列表;点击创建Bucket;修改Bucket名称;点击完成创建。注意复制Endpoint信息。

  5. 获取AccessKey ID和 AccessKey Secret。保存好AccessKey ID和 AccessKey Secret。
  6. 记录需要的四个信息。
    endpoint :在创建Bucket时选择地域,下面会有对应的Endpoint。
    bucketName :创建Bucket时自定义。
    AccessKey ID和 AccessKey Secret:加密获取。

2、上传文件

2.1 修改项目配置文件

在项目配置文件中定义endpoint、accessKeyId、accessKeySecret、bucketName四个信息。这里使用的是yaml格式配置文件。

java 复制代码
web:
  alioss:
    access-key-id: ---
    access-key-secret: ---
    bucket-name: ---
    endpoint: ---

2.2 定义一个Properties类获取配置信息

可以新建一个properties包,专门存放用于获取配置信息相关的类。

这里创建一个AliOssProperties类,用于保存与阿里云对象存储OSS服务相关的四个信息。

需要在该类上增加几个注解:

  • @Component:将该类注册成Bean;
  • @ConfigurationProperties:给prefix 属性赋值对应的配置文件信息。这里是"web.alioss"。该注解的作用是从配置文件获取配置信息,并将配置信息赋值非成员变量。需要注意配置文件中的名称与成员变量名一致,或者配置文件名使用 - 隔开,成员变量名使用驼峰命名法。
  • @Data:Lombok注解,生成get/set等方法。
java 复制代码
@Component // 将该类注册成Bean
@ConfigurationProperties(prefix = "web.alioss") // 从配置文件中获取配置信息赋值给成员变量
@Data // 生成get/set等方法
public class AliOssProperties {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

}

此处使用到了Lombok提供的注解,需要引入Lombok相关依赖:

java 复制代码
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

2.3 准备一个alioss工具类

阿里云官方提供许多简单实现代码供参考:阿里云对象存储文档中心。这里使用已经封装好的工具类。使用前需要引入阿里云oss相关依赖。

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

如果是Java9及以上版本,还需要添加JAXB相关依赖:

java 复制代码
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>

同样可以专门创建一个utils包存放工具类。可以看到工具类AliOssUtil中有四个成员变量,分别于四个关键信息对应。

java 复制代码
@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    /**
     * 文件上传
     *
     * @param bytes
     * @param objectName
     * @return
     */
    public String upload(byte[] bytes, String objectName) {

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

        try {
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } 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();
            }
        }

        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());

        return stringBuilder.toString();
    }
}

2.4 创建注册类,将AliOssUtil 注册成Bean

创建一个OssConfiguration 类,使用@Configuration 修饰,使其成为注册类。同时将配置文件中的配置信息传递给工具类的成员变量。配置类也可以创建一个config包存放。

java 复制代码
@Configuration // 配置类
@Slf4j
public class OssConfiguration {
    @Bean // 第三方Bean交给Spring容器管理
    @ConditionalOnMissingBean // 如果IOC容器中没有该Bean,则创建
    public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties) {
        log.info("开始创建阿里云文件上传工具类对象...");
        return new AliOssUtil(aliOssProperties.getEndpoint(),
                              aliOssProperties.getAccessKeyId(),
                              aliOssProperties.getAccessKeySecret(),
                              aliOssProperties.getBucketName());
    }
}

注意:

  1. 类上需要加@Configuration注解,使其成为注册类;
  2. 在类中定义一个方法。方法返回值类型是AliOssUtil 工具类。该方法传入参数为上述定义好的AliOssProperties类对象。在方法体中使用带参构造方法创建一个AliOssUtil 对象,并返回;
  3. 使用@Bean注解修饰该方法,第三方Bean交给Spring容器管理;
  4. 使用@ConditionalOnMissingBean注解,如果IOC容器中没有该Bean,则创建;

2.5 使用AliOssUtil 工具类上传文件

文件上传一般作为项目的controller层,由于是一个通用业务,所以一般会命名CommonController。

java 复制代码
@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {
    @Autowired
    private AliOssUtil aliOssUtil; // 1. 注入AliOssUtil Bean对象
    /**
     * 文件上传
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public Result<String> upload(MultipartFile file) { // 2. 使用MultipartFile 对象接收文件
        log.info("文件上传:{}", file);
        try {
            // 3. 获取原始文件名
            String originalFilename = file.getOriginalFilename(); 
            // 4. 获取原始文件名后缀
            int index = originalFilename.lastIndexOf(".");
            String extname = originalFilename.substring(index);
            // 5. 构建UUID随机文件名
            String newFilename = UUID.randomUUID().toString() + extname;
            // 6. 调用upload()方法上传文件
            String filePath = aliOssUtil.upload(file.getBytes(), newFilename);
            return Result.success(filePath);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("文件上传失败:{}", e);
        }
        return Result.error("文件上传失败...");
    }
}

这里接口的返回值为Restlt,是后端统一返回结果的格式。

java 复制代码
/**
 * 后端统一返回结果
 * @param <T>
 */
@Data
public class Result<T> implements Serializable {

    private Integer code; //编码:1成功,0和其它数字为失败
    private String msg; //错误信息
    private T data; //数据

    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.code = 1;
        return result;
    }

    public static <T> Result<T> success(T object) {
        Result<T> result = new Result<T>();
        result.data = object;
        result.code = 1;
        return result;
    }

    public static <T> Result<T> error(String msg) {
        Result result = new Result();
        result.msg = msg;
        result.code = 0;
        return result;
    }
}

2.6 注意事项

在controller接口中有两个地方值得注意:

  1. upload()接收的的参数类型是MultipartFile,SpringBoot默认上传的文件大小有限。当上传大文件时需要在配置文件中修改相关配置。
    max-file-size:指单个文件最大不超过10MB
    max-request-size:指一次请求的文件总量不超过100MB
java 复制代码
spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 100MB
  1. 在上传到阿里云前,需要对文件名进行修改,保证文件名唯一。可以使用UUID设置文件名。
相关推荐
THMOM911 分钟前
TinyWebserver学习(9)-HTTP
网络协议·学习·http
hello早上好3 分钟前
JDK 代理原理
java·spring boot·spring
PanZonghui8 分钟前
Centos项目部署之运行SpringBoot打包后的jar文件
linux·spring boot
PanZonghui8 分钟前
Centos项目部署之Java安装与配置
java·linux
沉着的码农39 分钟前
【设计模式】基于责任链模式的参数校验
java·spring boot·分布式
zyxzyx66643 分钟前
Flyway 介绍以及与 Spring Boot 集成指南
spring boot·笔记
凌辰揽月43 分钟前
Servlet学习
hive·学习·servlet
Mr_Xuhhh1 小时前
信号与槽的总结
java·开发语言·数据库·c++·qt·系统架构
纳兰青华1 小时前
bean注入的过程中,Property of ‘java.util.ArrayList‘ type cannot be injected by ‘List‘
java·开发语言·spring·list
coding and coffee1 小时前
狂神说 - Mybatis 学习笔记 --下
java·后端·mybatis