file-oss-management

统一协议:基于 AWS S3 SDK v2,兼容所有 S3 协议云服务

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "file-oss-management" with this command: npx skills add xu-cell/ai-engineering-init/xu-cell-ai-engineering-init-file-oss-management

文件与云存储指南

统一协议:基于 AWS S3 SDK v2,兼容所有 S3 协议云服务

架构概述

组件 说明

[你的OssClient]

统一操作入口(基于 AWS S3 SDK v2)

S3Client

AWS SDK 底层客户端

UploadResult

上传结果(url, filename, eTag)

一、S3 Client 初始化

import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.regions.Region;

// 通用 S3 客户端构建(兼容 MinIO / 阿里云 / 腾讯云等) S3Client s3Client = S3Client.builder() .endpointOverride(URI.create(endpoint)) .credentialsProvider(StaticCredentialsProvider.create( AwsBasicCredentials.create(accessKey, secretKey))) .region(Region.of(region)) .forcePathStyle(true) // MinIO 需要开启 .build();

二、文件上传

基础上传

import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.core.sync.RequestBody;

// 上传文件 PutObjectRequest request = PutObjectRequest.builder() .bucket(bucketName) .key("images/photo.jpg") .contentType("image/jpeg") .build();

s3Client.putObject(request, RequestBody.fromFile(file.toPath()));

// 上传输入流 s3Client.putObject(request, RequestBody.fromInputStream(inputStream, contentLength));

// 上传字节数组 s3Client.putObject(request, RequestBody.fromBytes(data));

封装上传服务(推荐模式)

@Service @RequiredArgsConstructor public class OssService {

private final S3Client s3Client;
private final OssProperties properties;

/**
 * 上传文件,自动生成路径
 */
public UploadResult upload(MultipartFile file) {
    String suffix = getFileSuffix(file.getOriginalFilename());
    String key = generateObjectKey(suffix);  // 如 2026/03/07/uuid.jpg

    PutObjectRequest request = PutObjectRequest.builder()
        .bucket(properties.getBucketName())
        .key(key)
        .contentType(file.getContentType())
        .build();

    s3Client.putObject(request,
        RequestBody.fromInputStream(file.getInputStream(), file.getSize()));

    return UploadResult.builder()
        .url(properties.getDomain() + "/" + key)
        .filename(key)
        .build();
}

private String generateObjectKey(String suffix) {
    String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
    return datePath + "/" + UUID.randomUUID() + suffix;
}

}

三、文件下载

import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.core.ResponseInputStream;

// 下载到输出流(推荐用于HTTP响应) GetObjectRequest getRequest = GetObjectRequest.builder() .bucket(bucketName) .key("images/photo.jpg") .build();

ResponseInputStream<?> response = s3Client.getObject(getRequest);

// 写入 HTTP 响应 try (InputStream is = response) { httpResponse.setContentType("image/jpeg"); httpResponse.setContentLengthLong(response.response().contentLength()); is.transferTo(httpResponse.getOutputStream()); }

四、文件删除

import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;

DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder() .bucket(bucketName) .key("images/photo.jpg") .build();

s3Client.deleteObject(deleteRequest);

五、预签名 URL

import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.*;

S3Presigner presigner = S3Presigner.builder() .endpointOverride(URI.create(endpoint)) .credentialsProvider(credentialsProvider) .region(Region.of(region)) .build();

// 下载预签名URL GetObjectPresignRequest getPresignRequest = GetObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(60)) .getObjectRequest(b -> b.bucket(bucketName).key("images/photo.jpg")) .build(); String downloadUrl = presigner.presignGetObject(getPresignRequest).url().toString();

// 上传预签名URL(前端直传) PutObjectPresignRequest putPresignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofHours(1)) .putObjectRequest(b -> b.bucket(bucketName).key("images/upload.jpg")) .build(); String uploadUrl = presigner.presignPutObject(putPresignRequest).url().toString();

六、Controller 接口(设计模式)

@RestController @RequiredArgsConstructor @RequestMapping("/api/oss") public class OssController {

private final OssService ossService;

@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public UploadResult upload(@RequestPart("file") MultipartFile file) {
    return ossService.upload(file);
}

@GetMapping("/download/{id}")
public void download(@PathVariable Long id, HttpServletResponse response) throws IOException {
    ossService.download(id, response);
}

@DeleteMapping("/{ids}")
public void delete(@PathVariable List&#x3C;Long> ids) {
    ossService.deleteByIds(ids);
}

}

七、配置模型

application.yml

oss: endpoint: https://s3.amazonaws.com # 或 MinIO/阿里云/腾讯云端点 access-key: your-access-key secret-key: your-secret-key bucket-name: your-bucket region: us-east-1 domain: https://cdn.example.com # 自定义域名(可选)

@Data @ConfigurationProperties(prefix = "oss") public class OssProperties { private String endpoint; private String accessKey; private String secretKey; private String bucketName; private String region; private String domain; }

八、服务商对照

服务商 endpoint 示例 备注

阿里云 OSS https://oss-cn-hangzhou.aliyuncs.com

S3 兼容

腾讯云 COS https://cos.ap-guangzhou.myqcloud.com

S3 兼容

七牛云 https://s3-cn-south-1.qiniucs.com

S3 兼容

MinIO http://localhost:9000

需 forcePathStyle(true)

AWS S3 https://s3.amazonaws.com

原生支持

九、设计要点

  • 统一封装:通过 S3 协议统一对接多个云服务商,切换只需改配置

  • 路径生成:按日期+UUID生成对象路径,避免冲突

  • 私有桶:私有桶文件通过预签名URL访问,设置合理的过期时间

  • 文件记录:上传后保存数据库记录,关联业务数据

  • 大文件:超过 100MB 考虑分片上传(CreateMultipartUpload )

  • 安全:前端直传使用预签名URL,不暴露密钥

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

scheduled-jobs

No summary provided by upstream source.

Repository SourceNeeds Review
General

loki-log-query

No summary provided by upstream source.

Repository SourceNeeds Review
General

openspec-new-change

No summary provided by upstream source.

Repository SourceNeeds Review
General

collaborating-with-gemini

No summary provided by upstream source.

Repository SourceNeeds Review