Spring Boot项目中实现文件上传功能的示例

网友投稿 281 2023-02-14

Spring Boot项目中实现文件上传功能的示例

在实际项目中,文件上传是很多项目必不可少的一个功能。那么在 Spring Boot 项目中又是如何来实现文件上传功能的呢?一般来说,上传的文件可以保存到项目根目录下的某一文件夹中,但这样做显然是不太合适的。因此我们选择将文件上传到专门的文件服务器中。很多云计算厂商都提供文件存储服务。这里我选择的是阿里云的对象存储(OSS)。

一、配置OSS

1. 导入SDK

首先,你需要注册阿里云的账号并开通对象存储服务。在准备工作完成之后,需要导入 java 版本的 SDK,这里使用 maven 进行导入

aliyun-sdk-oss

3.8.0

2. 修改配置文件

导入完成后在 application.properties 配置文件中添加以VgbRekZTc下内容

# 节点域名

aliyun.oss.endpoint=oss-cn-xxxxxxx.aliyuncs.com

# 账户id

aliyun.oss.accessKeyId=xxxxxxxxxxxxx

# 账户密码

aliVgbRekZTcyun.oss.accessKeySecret=xxxxxxxxxxxxx

# bucket名称

aliyun.oss.bucketName=xxxxxxxxxxx

# 签名过期时间

aliyun.oss.policy.expire=300

# 上传文件的最大尺寸

aliyun.oss.maxSize=10

# 上传地址的前缀

aliyun.oss.dir.prefix=xxx

# 回调参数的请求地址

aliyun.oss.callback=http://xxxxxx.com/api/aliyun/oss/callback

以上内容在开通服务后均可获取到,请根据实际情况进行修改

3. 初始化

OSSClient是OSS的Java客户端,用于管理存储空间和文件等OSS资源。使用Java SDK发起OSS请求,您需要初始化一个OSSClient实例,并根据需要修改ClientConfiguration的默认配置项。

根据官方文档的描述,需要初始化一个ossClient实例并将其注入到Spring容器中,因此可以编写一个配置类OssConfig

@Configuration

@PropertySource(value = {"classpath:application.properties"}, encoding = "utf-8")

public class OssConfig {

@Value("${aliyun.oss.endpoint}")

private String endpoint;

@Value("${aliyun.oss.accessKeyId}")

private String accessKeyId;

@Value("${aliyun.oss.accessKeySecret}")

private String secretAccessKey;

@Bean

public OSS ossClient(){

return new OSSClientBuilder().build(endpoint, accessKeyId, secretAccessKey);

}

}

更多详细的配置,请参考官方文档:初始化

二、文件上传

1. 流程分析

我们以典型的表单上传为例,在使用对象存储OSS后,表单上传分为以下几个流程:

注:Policy表单域用于验证请求的合法性。例如可以指定上传的大小,可以指定上传的Object名称等,上传成功后客户端跳转到的URL,上传成功后客户端收到的状态码。

PolicyConditions policyConds = new PolicyConditions();

policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);

policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, DIR_PREFIX);

String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);

byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);

// 将Policy字符串进行base64编码

String policy = BinaryUtil.toBase64String(binaryData);

// 用OSS的AccessKeySecret对base64编码后的Policy进行签名

String signature = ossClient.calculatePostSignature(postPolicy);

前端向OSS服务器上传文件时要上传Policy表单域,OSS服务器将对Policy表单域的内容进行验证。关于 Post Policy 的详细内容,请参考官方文档:Post Policy

当文件上传成功后,OSS服务器会向应用服务器发起回调请求,具体流程如下:

用户只需要在发送给 OSS 的请求中携带相应的 Callback 参数,即能实现回调。

Callback 参数是由一段经过 base64 编码的 jsON 字符串(字段)。构建 callback 参数的关键是指定请求回调的服务器 URL(callbackUrl)以及回调的内容(callbackBody)。

// 上传回调参数

Callback callback = new Callback();

// 指定请求回调的服务器URL

callback.setCallbackUrl(CALLBACK);

//(可选)设置回调请求消息头中Host的值,即您的服务器配置Host的值。

// callback.setCallbackHost("yourCallbackHost");

// 设置发起回调时请求body的值。

callback.setCallbackBody("{\\\"filename\\\":${object},\\\"mineType\\\":${mimeType}}");

// 设置发起回调请求的Content-Type。

callback.setCalbackBodyType(Callback.CalbackBodyType.JSON);

// 设置发起回调请求的自定义参数,由Key和Value组成,Key必须以x:开始。

// callback.addCallbackVar("x:dir", "value");

更详细的内容请阅读官方文档:Callback

2. 功能实现

首先编写 Post Policy 封装对象OssPolicyResult

@Data

public class OssPolicyResult {

@ApiModelProperty("用户id")

private String accessKeyId;

@ApiModelProperty("Post Policy经过base64编码过的字符串")

private String policy;

@ApiModelProperty("对policy签名后的字符串")

private String signature;

// @ApiModelProperty("对象的键值")

// private String key;

@ApiModelProperty("上传文件夹路径前缀")

private String dir;

@ApiModelProperty("oss对外服务的访问域名")

private String host;

@ApiModelProperty("上传成功后的回调设置")

private String callback;

}

然后需自定义一个回调结果对象OssCallBackResult

@Data

public class OssCallBackResult {

@ApiModelProperty("文件的链接")

private String url;

@ApiModelProperty("文件名称")

private String filename;

@ApiModelProperty("文件大小")

private String size;

@ApiModelProperty("文件的mimeType")

private String mimeType;

@ApiModelProperty("图片文件的宽")

private String width;

@ApiModelProperty("图片文件的高")

private String height;

}

注:以上内容可根据实际需要进行修改

之后编写 Service 接口及实现类

Service 接口:

public interface OssService {

// 生成Post Policy

OssPolicyResult policy();

// 上传成功后的回调

OssCallBackResult callback(Map requestBody);

}

Service 实现类:

@Slf4j

@Service

@PropertySource(value = {"classpath:application.properties"}, encoding = "utf-8")

public class OssServiceImpl implements OssService {

@Value("${aliyun.oss.endpoint}")

private String ENDPOINT;

@Value("${aliyun.oss.accessKeyId}")

private String ACCESS_KEY_ID;

@Value("${aliyun.oss.accessKeySecret}")

private String SECRET_ACCESS_KEY;

@Value("${aliyun.oss.bucketName}")

private String BUCKET_NAME;

@Value("${aliyun.oss.policy.expire}")

private int EXPIRE;

@Value("${aliyun.oss.maxSize}")

private int MAX_SIZE;

@Value("${aliyun.oss.dir.prefix}")

private String DIR_PREFIX;

@Value("${aliyun.oss.callback}")

private String CALLBACK;

@Autowired

private OSS ossClient;

@Override

public OssPolicyResult policy() {

OssPolicyResult result = new OssPolicyResult();

// 签名有效期

long expireEndTime = System.currentTimeMillis() + EXPIRE * 1000;

Date expiration = new Date(expireEndTime);

// 文件名称

// String filename = UUID.randomUUID().toString();

// 文件大小

long maxSize = MAX_SIZE * 1024 * 1024;

// 提交节点

String action = "http://" + BUCKET_NAME + "." + ENDPOINT;

// 上传回调参数

Callback callback = new Callback();

// 指定请求回调的服务器URL

callback.setCallbackUrl(CALLBACK);

//(可选)设置回调请求消息头中Host的值,即您的服务器配置Host的值。

// callback.setCallbackHost("yourCallbackHost");

// 设置发起回调时请求body的值。

callback.setCallbackBody("{\\\"filename\\\":${object}}");

// 设置发起回调请求的Content-Type。

callback.setCalbackBodyType(Callback.CalbackBodyType.JSON);

// 设置发起回调请求的自定义参数,由Key和Value组成,Key必须以x:开始。

// callback.addCallbackVar("x:dir", "value");

try {

PolicyConditions policyConds = new PolicyConditions();

policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);

policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, DIR_PREFIX);

String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);

byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);

// 将Policy字符串进行base64编码

String policy = BinaryUtil.toBase64String(binaryData);

// 用OSS的AccessKeySecret对base64编码后的Policy进行签名

String signature = ossClient.calculatePostSignature(postPolicy);

// 将callback配置进行base64编码

String callbackData = BinaryUtil.toBase64String(OSSUtils.jsonizeCallback(callback).getBytes());

// 返回结果

result.setAccessKeyId(ACCESS_KEY_ID);

result.setPolicy(policy);

result.setSignature(signature);

// result.setKey(filename);

result.setDir(dir);

result.setHost(action);

result.setCallback(callbackData);

} catch (Exception e) {

log.error("签名生成失败", e);

}

return result;

}

@Override

public OssCallBackResult callback(Map requestBody) {

OssCallBackResult ossCallbackResult = new OssCallBackResult();

// 文件名

String filename = requestBody.get("filename").toString();

// 文件链接

String url = "https://" + BUCKET_NAME + "." + ENDPOINT + "/" + DIR_PREFIX + "/" + filename;

ossCallbackResult.setUrl(url);

return ossCallbackResult;

}

}

添加 Controller 层:

@Api(tags = "阿里云对象存储接口")

@RequestMapping("/api")

@RestController

public class OssController {

@Autowired

private OssService ossService;

@ApiOperation(value = "OSS上传签名生成")

@GetMapping("/aliyun/oss/policy")

public Object policy() {

return ossService.policy();

}

@ApiOperation(value = "OSS上传成功回调")

@PostMapping("/aliyun/oss/callback")

public Object callback(@RequestBody Map requestBody) {

return ossService.callback(requestBody);

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java利用正则表达式处理特殊字符的方法实例
下一篇:Mybatis批量提交实现步骤详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~