【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设置文件名。
相关推荐
小丁爱养花18 分钟前
JVM 面试八股文
java·jvm·面试
m0_7482365823 分钟前
解决Spring Boot中Druid连接池“discard long time none received connection“警告
spring boot·后端·oracle
Q_274378510925 分钟前
基于Spring Boot的车间调度管理系统
java·spring boot·后端
冰淇淋百宝箱28 分钟前
GraphRAG: Auto Prompt Tuning 实践
java·服务器·前端
爱吃水果蝙蝠汤31 分钟前
DATACOM-华为数通解决方案SDN、iMaster
网络·网络协议·学习·tcp/ip·华为
S-X-S1 小时前
日志模块新增配置日志根目录和项目模块功能
java·日志
miilue1 小时前
[LeetCode] 链表I — 704#设计链表 | 203#移除链表元素 | 206#反转链表 | 递归法
java·开发语言·c++·算法·leetcode·链表
月印千江6711 小时前
从密码学原理与应用新方向到移动身份认证与实践
经验分享·笔记·其他·网络安全·密码学
转角人生1 小时前
查看jar包,被哪些地方引用,并排包
java·ide·intellij-idea
bohu831 小时前
opencv笔记2
人工智能·笔记·opencv