当前位置: 首页 > news >正文

SpringBoot 3.x集成阿里云OSS:文件上传 断点续传 权限控制

SpringBoot 3.x集成阿里云OSS:文件上传/断点续传/权限控制

  • Spring Boot 3.x 集成阿里云 OSS 终极指南
  • 一、环境准备与依赖配置
    • 1. 添加阿里云 OSS SDK 依赖
    • 2. 配置 OSS 连接参数
  • 二、基础文件上传服务
    • 1. OSS 客户端配置
    • 2. 文件上传服务
  • 三、断点续传高级实现
    • 1. 断点续传服务
    • 2. 断点续传恢复机制
  • 四、精细化权限控制
    • 1. STS 临时凭证服务
    • 2. 前端直传签名服务
  • 五、SDK 坑位指南与最佳实践
    • 1. 常见问题解决方案
    • 2. 性能优化配置
    • 3. 安全最佳实践
  • 六、完整文件管理控制器
  • 七、部署与监控
    • 1. 健康检查端点
    • 2. Prometheus 监控指标
  • 八、总结与最佳实践
    • 1. 架构选择建议
    • 2. 安全防护措施
    • 3. 性能优化方案

Spring Boot 3.x 集成阿里云 OSS 终极指南

一、环境准备与依赖配置

1. 添加阿里云 OSS SDK 依赖

<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.1</version>
</dependency>

2. 配置 OSS 连接参数

# application.yml
aliyun:oss:endpoint: oss-cn-hangzhou.aliyuncs.com # 根据实际区域修改access-key-id: your-access-key-idaccess-key-secret: your-access-key-secretbucket-name: your-bucket-namests:role-arn: acs:ram::1234567890123456:role/oss-sts-role # RAM角色ARNpolicy: | # 权限策略{"Version": "1","Statement": [{"Effect": "Allow","Action": ["oss:GetObject","oss:PutObject"],"Resource": ["acs:oss:*:*:your-bucket-name/*"]}]}

二、基础文件上传服务

1. OSS 客户端配置

@Configuration
public class OssConfig {@Value("${aliyun.oss.endpoint}")private String endpoint;@Value("${aliyun.oss.access-key-id}")private String accessKeyId;@Value("${aliyun.oss.access-key-secret}")private String accessKeySecret;@Beanpublic OSS ossClient() {return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);}
}

2. 文件上传服务

@Service
@Slf4j
public class OssService {private final OSS ossClient;private final String bucketName;public OssService(OSS ossClient, @Value("${aliyun.oss.bucket-name}") String bucketName) {this.ossClient = ossClient;this.bucketName = bucketName;}/*** 简单文件上传* @param file 上传文件* @param objectKey 对象键(OSS路径)* @return 文件URL*/public String uploadFile(MultipartFile file, String objectKey) throws IOException {try (InputStream inputStream = file.getInputStream()) {ossClient.putObject(bucketName, objectKey, inputStream);return generateUrl(objectKey);} catch (Exception e) {log.error("文件上传失败: {}", objectKey, e);throw new OssException("文件上传失败");}}/*** 生成文件URL(带签名)*/private String generateUrl(String objectKey) {Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000); // 1小时有效return ossClient.generatePresignedUrl(bucketName, objectKey, expiration).toString();}
}

三、断点续传高级实现

1. 断点续传服务

@Service
public class ResumableUploadService {private final OSS ossClient;private final String bucketName;public ResumableUploadService(OSS ossClient, @Value("${aliyun.oss.bucket-name}") String bucketName) {this.ossClient = ossClient;this.bucketName = bucketName;}/*** 断点续传上传* @param file 上传文件* @param objectKey 对象键* @return 上传结果*/public UploadResult resumableUpload(MultipartFile file, String objectKey) {try {// 创建上传请求UploadFileRequest request = new UploadFileRequest(bucketName, objectKey,file.getInputStream(),file.getSize());// 配置上传参数request.setPartSize(5 * 1024 * 1024); // 5MB分片request.setTaskNum(5); // 并发线程数request.setEnableCheckpoint(true); // 开启断点记录// 设置断点文件存储位置String checkpointDir = System.getProperty("java.io.tmpdir") + "/oss-checkpoints";request.setCheckpointFile(checkpointDir + "/" + objectKey + ".ucp");// 执行上传UploadFileResult result = ossClient.uploadFile(request);return new UploadResult(generateUrl(objectKey),result.getMultipartUploadResult().getETag(),result.getMultipartUploadResult().getLocation());} catch (Throwable e) {throw new OssException("断点续传失败", e);}}@Data@AllArgsConstructorpublic static class UploadResult {private String fileUrl;private String eTag;private String location;}
}

2. 断点续传恢复机制

public void resumeUpload(String objectKey) {String checkpointFile = getCheckpointFilePath(objectKey);if (new File(checkpointFile).exists()) {UploadFileRequest request = new UploadFileRequest(bucketName, objectKey);request.setCheckpointFile(checkpointFile);try {ossClient.uploadFile(request);} catch (Throwable e) {throw new OssException("续传失败", e);}} else {throw new OssException("未找到断点记录");}
}

四、精细化权限控制

1. STS 临时凭证服务

@Service
public class StsService {@Value("${aliyun.oss.sts.role-arn}")private String roleArn;@Value("${aliyun.oss.sts.policy}")private String policy;@Value("${aliyun.oss.access-key-id}")private String accessKeyId;@Value("${aliyun.oss.access-key-secret}")private String accessKeySecret;/*** 获取STS临时凭证* @param sessionName 会话名称* @param durationSeconds 有效期(秒)* @return STS凭证*/public StsToken getStsToken(String sessionName, long durationSeconds) {DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);IAcsClient client = new DefaultAcsClient(profile);AssumeRoleRequest request = new AssumeRoleRequest();request.setRoleArn(roleArn);request.setRoleSessionName(sessionName);request.setDurationSeconds(durationSeconds);request.setPolicy(policy);try {AssumeRoleResponse response = client.getAcsResponse(request);AssumeRoleResponse.Credentials credentials = response.getCredentials();return new StsToken(credentials.getAccessKeyId(),credentials.getAccessKeySecret(),credentials.getSecurityToken(),credentials.getExpiration());} catch (ClientException e) {throw new StsException("STS获取失败", e);}}@Data@AllArgsConstructorpublic static class StsToken {private String accessKeyId;private String accessKeySecret;private String securityToken;private String expiration;}
}

2. 前端直传签名服务

@Service
public class OssSignatureService {private final OSS ossClient;private final String bucketName;public OssSignatureService(OSS ossClient, @Value("${aliyun.oss.bucket-name}") String bucketName) {this.ossClient = ossClient;this.bucketName = bucketName;}/*** 生成前端直传签名* @param objectKey 对象键* @param expireSeconds 过期时间(秒)* @return 签名信息*/public SignatureInfo generateSignature(String objectKey, long expireSeconds) {Date expiration = new Date(System.currentTimeMillis() + expireSeconds * 1000);// 创建策略PolicyConditions policy = new PolicyConditions();policy.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 104857600); // 100MB限制policy.addConditionItem(PolicyConditions.COND_KEY, objectKey);// 生成签名String postPolicy = ossClient.generatePostPolicy(expiration, policy);String encodedPolicy = BinaryUtil.toBase64String(postPolicy.getBytes());String signature = ossClient.calculatePostSignature(postPolicy);return new SignatureInfo(ossClient.getEndpoint().toString(),bucketName,objectKey,encodedPolicy,signature,expiration);}@Data@AllArgsConstructorpublic static class SignatureInfo {private String endpoint;private String bucket;private String key;private String policy;private String signature;private Date expiration;}
}

五、SDK 坑位指南与最佳实践

1. 常见问题解决方案

问题类型现象解决方案
连接超时上传大文件时超时增加超时时间:
ossClient.setTimeout(300000)
内存溢出大文件上传时OOM使用文件流代替内存流:
request.setUploadFile(filePath)
分片失败分片上传卡死设置合理的分片大小:
request.setPartSize(5 * 1024 * 1024)
签名失效前端直传签名过期签名有效期至少600秒,建议1200秒
权限不足STS操作失败检查RAM角色权限策略

2. 性能优化配置

@Bean
public OSS ossClient(OssProperties properties) {ClientBuilderConfiguration config = new ClientBuilderConfiguration();// 连接池配置config.setMaxConnections(200); // 最大连接数config.setConnectionTimeout(30 * 1000); // 连接超时30sconfig.setSocketTimeout(120 * 1000); // 读写超时120s// 开启HTTP重试config.setMaxErrorRetry(3); // 开启HTTPSconfig.setProtocol(Protocol.HTTPS);return new OSSClientBuilder().build(properties.getEndpoint(), properties.getAccessKeyId(), properties.getAccessKeySecret(),config);
}

3. 安全最佳实践

/*** 安全文件上传验证*/
public void validateFileUpload(MultipartFile file, String objectKey) {// 1. 文件类型验证String contentType = file.getContentType();if (!Arrays.asList("image/jpeg", "image/png").contains(contentType)) {throw new OssException("不支持的文件类型");}// 2. 文件大小验证if (file.getSize() > 10 * 1024 * 1024) { // 10MB限制throw new OssException("文件大小超过限制");}// 3. 文件名安全过滤if (objectKey.contains("..") || objectKey.contains("/")) {throw new OssException("非法文件名");}// 4. 病毒扫描(集成第三方服务)if (!virusScanService.scan(file)) {throw new OssException("文件安全检测未通过");}
}

六、完整文件管理控制器

@RestController
@RequestMapping("/oss")
@RequiredArgsConstructor
public class OssController {private final OssService ossService;private final ResumableUploadService resumableService;private final StsService stsService;private final OssSignatureService signatureService;/*** 普通文件上传*/@PostMapping("/upload")public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file,@RequestParam("path") String path) throws IOException {String objectKey = "uploads/" + path + "/" + file.getOriginalFilename();String url = ossService.uploadFile(file, objectKey);return ResponseEntity.ok(url);}/*** 断点续传接口*/@PostMapping("/resumable-upload")public ResponseEntity<ResumableUploadService.UploadResult> resumableUpload(@RequestParam("file") MultipartFile file,@RequestParam("path") String path) {String objectKey = "uploads/" + path + "/" + file.getOriginalFilename();return ResponseEntity.ok(resumableService.resumableUpload(file, objectKey));}/*** 获取STS临时凭证*/@GetMapping("/sts-token")public ResponseEntity<StsService.StsToken> getStsToken() {String sessionName = "user-" + SecurityUtils.getCurrentUserId();return ResponseEntity.ok(stsService.getStsToken(sessionName, 3600));}/*** 生成前端直传签名*/@GetMapping("/signature")public ResponseEntity<OssSignatureService.SignatureInfo> getSignature(@RequestParam String fileName) {String objectKey = "uploads/user/" + SecurityUtils.getCurrentUserId() + "/" + fileName;return ResponseEntity.ok(signatureService.generateSignature(objectKey, 1200));}
}

七、部署与监控

1. 健康检查端点

@RestController
@RequestMapping("/actuator")
public class OssHealthController {private final OSS ossClient;private final String bucketName;@GetMapping("/oss-health")public ResponseEntity<String> checkOssHealth() {try {boolean exists = ossClient.doesBucketExist(bucketName);return exists ? ResponseEntity.ok("OSS connection is healthy") :ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("Bucket not found");} catch (Exception e) {return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("OSS connection failed: " + e.getMessage());}}
}

2. Prometheus 监控指标

@Bean
public MeterRegistryCustomizer<MeterRegistry> ossMetrics(OSS ossClient) {return registry -> {Gauge.builder("oss.connection.count", ossClient, client -> client.getClientConfiguration().getMaxConnections()).description("OSS connection pool size").register(registry);Counter.builder("oss.upload.count").description("Total OSS upload operations").register(registry);};
}

八、总结与最佳实践

1. 架构选择建议

  • 小文件上传:直接使用简单上传接口
  • 大文件上传:使用断点续传(>10MB)
  • 前端直传:使用STS临时凭证或签名直传
  • 敏感文件:服务端中转上传+病毒扫描

2. 安全防护措施

  1. 权限最小化:STS策略只授予必要权限
  2. 文件类型过滤:限制可上传文件类型
  3. 病毒扫描:集成ClamAV等扫描引擎
  4. 访问日志:开启OSS访问日志审计
  5. WAF防护:配置Web应用防火墙规则

3. 性能优化方案

小文件
大文件
前端直传
客户端
直接上传
分片上传
并发上传
OSS服务端合并
签名/STS
绕过应用服务器

通过本方案,可实现安全高效的OSS文件管理,支持从KB到TB级文件的上传需求,同时满足企业级安全合规要求。


文章转载自:
http://accession.lbooon.cn
http://bardic.lbooon.cn
http://armadillo.lbooon.cn
http://aftertime.lbooon.cn
http://binder.lbooon.cn
http://characterisation.lbooon.cn
http://cardiography.lbooon.cn
http://anabolic.lbooon.cn
http://apophthegmatic.lbooon.cn
http://candid.lbooon.cn
http://bellboy.lbooon.cn
http://anaesthesiologist.lbooon.cn
http://academician.lbooon.cn
http://aghan.lbooon.cn
http://caressing.lbooon.cn
http://alchemistically.lbooon.cn
http://actualite.lbooon.cn
http://azygous.lbooon.cn
http://bantu.lbooon.cn
http://ascosporic.lbooon.cn
http://artsy.lbooon.cn
http://approachable.lbooon.cn
http://avocatory.lbooon.cn
http://cannily.lbooon.cn
http://ascendence.lbooon.cn
http://camellia.lbooon.cn
http://backwater.lbooon.cn
http://bottomland.lbooon.cn
http://antidotal.lbooon.cn
http://baffleplate.lbooon.cn
http://www.dtcms.com/a/280919.html

相关文章:

  • 填补空白!openKylin率先完成RISC-V商业打印驱动全适配
  • AI问答-Token:在人工智能领域,Token 是模型处理文本的核心单元 / 最小可处理片段
  • Python打卡训练营Day58
  • 大白话解释一下RTC实时时钟
  • 【机器学习深度学习】大模型推理速度与私有化部署的价值分析
  • 元宇宙内容生产工具终局之战:三维编辑、实时协同与跨平台发布的黄金三角
  • 2025年夏Datawhale AI夏令营机器学习
  • Springboot 项目 连接人大金仓数据库,进行功能查询demo示例
  • pytorch学习笔记(四)-- TorchVision 物体检测微调教程
  • 图像修复:深度学习实现老照片划痕修复+老照片上色
  • 一文读懂循环神经网络—门控循环单元
  • 深度学习 Pytorch图像分类步骤
  • 僵尸进程Zombie Process
  • 如何通过 WebSocket 接口订阅实时外汇行情数据(PHP 示例)
  • dom节点操作方法与事件冒泡总结
  • Python爬虫实战:研究Mistune库相关技术
  • Android中Launcher简介
  • 【SOA用于噪声抑制】光纤DFB激光器中弛豫振荡噪声抑制
  • Android原生Dialog
  • 关于我用AI编写了一个聊天机器人……(番外1)
  • 博客项目 laravel vue mysql 第六章 文章功能
  • PHP:从入门到实战的全面指南
  • 【PTA数据结构 | C语言版】构造二叉树
  • python原生处理properties文件
  • curl请求一直等待但是postman访问正常的问题处理
  • 视频HDR技术全解析:从原理到应用的深度探索
  • IDEA中删除多余的jdk选项 【IDEA2024版】
  • 企业培训视频如何做内容加密防下载防盗录(功能点整理)
  • 零信任安全架构:如何在云环境中重构网络边界?
  • Wing FTP服务器漏洞正遭活跃利用,CVSS评分10分