13 KiB
上小节 中,我们已经将 Minio 文件策略类的上传文件逻辑编写好了,本小节中,把剩下的上传文件到阿里云 OSS 的功能也敲一下。
开通服务
首先,咱们需要登录阿里云官网,并访问对象存储 OSS 产品首页:https://www.aliyun.com/product/oss ,如下图所示,点击立即开通按钮,开通服务:
开通成功后,进入到对象存储 OSS 控制台, 点击 Bucket 列表:
在 Bucket 列表中,点击上方的创建 Bucket 按钮,准备创建桶:
填写 Bucket 相关配置项,如下:
- 模式选择:勾选自定义创建;
- Bucket 名称:这里填写
xiaohashu;- 地域:推荐选择离你产品使用者较近的地方,有助于提升访问速度。
- 阻止公共访问:关闭掉,并将读写权限修改为公共读;
配置填写完毕后,点击完成创建按钮,并确认要创建。
Bucket 创建成功后,在列表页中就可以看到新创建的 xiaohashu 桶了,如上图所示。
获取 AccessKey 接入凭证
通过代码上传文件到 Bucket ,阿里云需要校验你的身份,还需要获取一下接入凭证。点击回到阿里云首页,将鼠标移动到登录用户的头像上,即可看到 AccessKey 选项,点击即可查看:
Tip
: 记得给你的账号充值一点钱,比如 1 块钱,因为图片的访问会产生流量费用。
将你的 AccessKeyID 以及 AccessKey Secret 复制出来:
修改配置格式
编辑 xiaohashu-oss-biz 模块的 application-dev.yml 开发环境配置,修改一下 minio 配置项的结构,统一放置到 storage 节点下,方便统一维护。再额外加一下阿里云 OSS 需要用到的配置项,如下:
#=================================================================
# 对象存储配置
#=================================================================
storage:
minio:
endpoint: http://127.0.0.1:9000
accessKey: quanxiaoha
secretKey: quanxiaoha
aliyun-oss:
endpoint: oss-cn-hangzhou.aliyuncs.com # 改成你自己的
accessKey: xxx # 改成你自己的
secretKey: xxx # 改成你自己的
因为配置文件中 minio 配置项的结构变动了,对应的,MinioProperties 配置类的 @ConfigurationProperties 注解的值也需要修正一下,修改为 storage.minio, 代码如下:
package com.quanxiaoha.xiaohashu.oss.biz.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author: 犬小哈
* @url: www.quanxiaoha.com
* @date: 2023-05-11 8:49
* @description: Minio 配置项
**/
@ConfigurationProperties(prefix = "storage.minio")
@Component
@Data
public class MinioProperties {
private String endpoint;
private String accessKey;
private String secretKey;
}
添加阿里云 OSS 配置类
顺便把阿里云 OSS 配置项对应的配置类也创建一下,代码如下:
package com.quanxiaoha.xiaohashu.oss.biz.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author: 犬小哈
* @url: www.quanxiaoha.com
* @date: 2023-05-11 8:49
* @description: 阿里云 OSS 配置项
**/
@ConfigurationProperties(prefix = "storage.aliyun-oss")
@Component
@Data
public class AliyunOSSProperties {
private String endpoint;
private String accessKey;
private String secretKey;
}
添加依赖
前置工作完成后,开始添加阿里云 OSS 对象存储的 SDK 依赖,可访问官方文档:https://help.aliyun.com/zh/oss/ 查看详细内容。这里直接演示如何操作,编辑项目最外层的 pom.xml 文件,声明相关版本号与依赖,代码如下:
<properties>
// 省略...
<minio.version>8.2.1</minio.version>
<aliyun-sdk-oss.version>3.17.4</aliyun-sdk-oss.version>
<jaxb-api.version>2.3.1</jaxb-api.version>
<activation.version>1.1.1</activation.version>
<jaxb-runtime.version>2.3.3</jaxb-runtime.version>
</properties>
<!-- 统一依赖管理 -->
<dependencyManagement>
<dependencies>
// 省略...
<!-- 阿里云 OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-sdk-oss.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-api.version}</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${activation.version}</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>${jaxb-runtime.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
接着,编辑 xiaohashu-oss-biz 模块的 pom.xml 文件,引入上述依赖:
<dependencies>
// 省略...
<!-- 阿里云 OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
</dependencies>
依赖添加完毕后,点击右侧栏 Reload 图标,重新刷新一下 Maven 依赖,将包下载到本地 Maven 仓库中。
初始化客户端
然后,在 /config 包下创建 AliyunOSSConfig 配置类,代码如下,用于初始化 OSS 客户端实体类,并注入到 Spring 容器中:
package com.quanxiaoha.xiaohashu.oss.biz.config;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: 犬小哈
* @url: www.quanxiaoha.com
* @date: 2023-05-11 8:49
* @description: 阿里云 Client 配置
**/
@Configuration
public class AliyunOSSConfig {
@Resource
private AliyunOSSProperties aliyunOSSProperties;
/**
* 构建 阿里云 OSS 客户端
*
* @return
*/
@Bean
public OSS aliyunOSSClient() {
// 设置访问凭证
DefaultCredentialProvider credentialsProvider = CredentialsProviderFactory.newDefaultCredentialProvider(
aliyunOSSProperties.getAccessKey(), aliyunOSSProperties.getSecretKey());
// 创建 OSSClient 实例
return new OSSClientBuilder().build(aliyunOSSProperties.getEndpoint(), credentialsProvider);
}
}
补充阿里云策略实现类
客户端初始化完毕后,编辑 AliyunOSSFileStrategy 阿里云策略实现类,补充上传文件功能,代码如下:
package com.quanxiaoha.xiaohashu.oss.biz.strategy.impl;
import com.aliyun.oss.OSS;
import com.quanxiaoha.xiaohashu.oss.biz.config.AliyunOSSProperties;
import com.quanxiaoha.xiaohashu.oss.biz.strategy.FileStrategy;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.util.UUID;
/**
* @author: 犬小哈
* @date: 2024/6/27 19:47
* @version: v1.0.0
* @description: 阿里云 OSS 文件上传策略
**/
@Slf4j
public class AliyunOSSFileStrategy implements FileStrategy {
@Resource
private AliyunOSSProperties aliyunOSSProperties;
@Resource
private OSS ossClient;
@Override
@SneakyThrows
public String uploadFile(MultipartFile file, String bucketName) {
log.info("## 上传文件至阿里云 OSS ...");
// 判断文件是否为空
if (file == null || file.getSize() == 0) {
log.error("==> 上传文件异常:文件大小为空 ...");
throw new RuntimeException("文件大小不能为空");
}
// 文件的原始名称
String originalFileName = file.getOriginalFilename();
// 生成存储对象的名称(将 UUID 字符串中的 - 替换成空字符串)
String key = UUID.randomUUID().toString().replace("-", "");
// 获取文件的后缀,如 .jpg
String suffix = originalFileName.substring(originalFileName.lastIndexOf("."));
// 拼接上文件后缀,即为要存储的文件名
String objectName = String.format("%s%s", key, suffix);
log.info("==> 开始上传文件至阿里云 OSS, ObjectName: {}", objectName);
// 上传文件至阿里云 OSS
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(file.getInputStream().readAllBytes()));
// 返回文件的访问链接
String url = String.format("https://%s.%s/%s", bucketName, aliyunOSSProperties.getEndpoint(), objectName);
log.info("==> 上传文件至阿里云 OSS 成功,访问路径: {}", url);
return url;
}
}
大体上和
minio差不太多,细节部分需要注意一下,如:
自测一波
功能敲写完毕后,重启对象存储服务。登录到 Nacos 控制台,将对象存储类型切换到 aliyun , 以便测试对应功能。打开 Apipost 工具,测试一波上传图片接口,如下:
可以看到,成功返回了阿里云 OSS 的图片访问地址。也可以进入到阿里云后台文件列表中,确认一下图片是否真的上传成功了:
关于图片浏览器无法预览的问题
如果你直接将图片链接复制到浏览器中进行访问,会发现图片直接就下载了,而不是预览模式。这个不是代码写的有问题,官方有解释这个问题:
官方解释如下:
使用OSS默认域名或传输加速域名访问。出于数据传输安全考虑,当使用OSS默认域名或传输加速域名访问某个时间点创建的Bucket内的特定类型文件时(例如Content-Type为text/html、image/jpeg等),OSS会强制在返回头中增加下载Header(
x-oss-force-download: true和Content-Disposition: attachment)。标准浏览器检测到Content-Disposition: attachment时,会出现强制下载而不是预览行为。
解决方案是:
您需要使用自定义域名访问。
可以先不用管,不影响到时候前端 <img> 标签图片展示。