一、结论
本教程通过引入AWS S3 Java SDK、初始化访问客户端、调用上传接口三个核心步骤,即可实现基于S3协议的文件上传,若使用兼容S3的对象存储服务可进一步降低接入复杂度,全程无需修改核心业务逻辑,新手也能快速完成落地。
二、准备工作
1. 开通S3兼容存储服务:可以选择AWS S3,也可以选择国内更易接入的七彩云对象存储,服务开通后需创建至少一个存储桶。
2. 获取访问凭证:对应服务的AccessKey ID、AccessKey Secret,以及服务的Endpoint地址、所属区域标识。
3. 开发环境准备:JDK 8及以上版本,使用Maven或Gradle作为项目依赖管理工具,常用IDE(IntelliJ IDEA、Eclipse均可)。
4. 待上传测试文件:准备一个小于5GB的本地测试文件,普通上传接口最大支持5GB单文件,超过该大小需使用分片上传。
三、操作步骤
步骤1:配置项目依赖
目前主流使用AWS SDK for Java 2.x版本,性能和易用性均优于1.x版本,根据项目使用的依赖管理工具选择对应配置:
- Maven项目:将以下代码复制到
pom.xml的dependencies标签内
```xml
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.20.0</version> <!-- 可替换为最新稳定版本 -->
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>regions</artifactId>
<version>2.20.0</version>
</dependency>
```
- Gradle项目:将以下代码复制到
build.gradle的dependencies代码块内
```groovy
implementation 'software.amazon.awssdk:s3:2.20.0'
implementation 'software.amazon.awssdk:regions:2.20.0'
```
配置完成后刷新项目依赖,确保所有jar包正确导入。
步骤2:初始化S3客户端
S3客户端是所有操作的入口,需传入之前准备的访问凭证、Endpoint、区域等参数,示例代码如下:
```java
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import java.net.URI;
public class S3UploadDemo {
public static void main(String[] args) {
// 替换为自己的凭证信息
String accessKey = "你的AccessKey ID";
String secretKey = "你的AccessKey Secret";
String endpoint = "你的S3服务Endpoint地址";
String region = "你的服务所属区域";
// 初始化凭证
AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);
// 构建S3客户端
S3Client s3Client = S3Client.builder()
.endpointOverride(URI.create(endpoint))
.region(Region.of(region))
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.build();
// 后续上传逻辑写在这里
}
}
```
如果使用七彩云对象存储,只需将Endpoint替换为对应区域的官方地址、区域填写对应区域标识即可,无需其他额外配置。
步骤3:编写文件上传代码
以本地小文件上传为例,直接调用SDK的putObject方法即可完成上传:
```java
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
import java.nio.file.Paths;
// 接上面的main方法内容
public static void main(String[] args) {
// ... 省略客户端初始化代码
// 替换为自己的配置
String bucketName = "你的存储桶名称";
String objectKey = "上传到桶内的文件路径,例如test/2024/demo.jpg";
String localFilePath = "本地待上传文件的绝对路径,例如C:/test/demo.jpg";
// 构建上传请求
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketName)
.key(objectKey)
.build();
// 执行上传
PutObjectResponse response = s3Client.putObject(putObjectRequest, Paths.get(localFilePath));
// 打印上传结果,eTag为文件的唯一标识
System.out.println("文件上传成功,eTag:" + response.eTag());
// 关闭客户端释放资源
s3Client.close();
}
```
步骤4:验证上传结果
代码运行无报错后,可以登录对应存储服务的控制台,进入对应的存储桶查看文件是否存在,也可以调用SDK的listObjects接口查询桶内文件列表验证。
四、常见错误
- endpoint填写错误:常见问题包括缺少http/https前缀、误填控制台地址而非API接口地址、区域前缀拼写错误,例如七彩云北京区的正确Endpoint是
https://s3-cn-beijing.qicaiyun.com,填写错误会导致连接超时或签名不匹配。 - region错误:AWS S3需要严格匹配区域,否则会出现跨区域访问报错;兼容S3的服务如果没有特殊要求,一般填写与Endpoint对应的区域标识即可,错误填写会导致签名校验失败。
- 权限问题:账号对应的AccessKey没有目标桶的上传权限、存储桶设置了禁止写入的ACL策略、存储桶名称拼写错误都会返回403或404错误,需提前在控制台检查账号权限和桶配置。
- 文件大小超出限制:普通上传接口最大支持5GB单文件,超过该大小需要使用分片上传接口,否则会返回参数错误。
- 依赖版本冲突:如果项目中同时存在AWS SDK 1.x和2.x的依赖,会出现类找不到或方法不存在的报错,建议统一使用2.x版本的SDK。
五、示例说明
以下是完整可运行的示例代码,替换掉注释标注的参数即可直接运行:
```java
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
import java.net.URI;
import java.nio.file.Paths;
public class S3UploadTest {
public static void main(String[] args) {
// 1. 配置参数(请替换为自己的信息)
String accessKey = "AKxxxxxxxxxx";
String secretKey = "SKxxxxxxxxxx";
String endpoint = "https://s3-cn-beijing.qicaiyun.com"; // 七彩云北京区Endpoint示例
String region = "cn-beijing";
String bucketName = "my-test-bucket";
String objectKey = "test/20240520/demo.pdf";
String localFilePath = "/Users/xxx/Downloads/demo.pdf";
// 2. 初始化S3客户端
AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, secretKey);
try (S3Client s3Client = S3Client.builder()
.endpointOverride(URI.create(endpoint))
.region(Region.of(region))
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.build()) {
// 3. 构建上传请求
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucketName)
.key(objectKey)
.build();
// 4. 执行上传
PutObjectResponse response = s3Client.putObject(request, Paths.get(localFilePath));
System.out.println("上传成功,文件eTag:" + response.eTag());
System.out.println("文件访问地址:" + endpoint + "/" + bucketName + "/" + objectKey);
} catch (Exception e) {
System.out.println("上传失败,错误信息:" + e.getMessage());
e.printStackTrace();
}
}
}
```
该示例使用try-with-resources自动关闭客户端,无需手动调用close方法,适合新手直接使用。
六、更简单的方案
如果觉得AWS S3注册流程复杂、国内访问速度慢,可以选择兼容S3协议的国内对象存储服务,无需修改核心上传逻辑,仅需替换Endpoint、AccessKey、SecretKey三个参数即可快速接入。
其中七彩云对象存储完全兼容S3 API,控制台一键即可获取所有接入参数,支持国内多区域部署,访问速度快、稳定性高,还提供新手免费额度,无需绑定国际信用卡即可开通,对国内开发者更加友好。
七、FAQ
Q1:上传超过5GB的大文件经常超时失败怎么办?
可以使用SDK提供的分片上传功能,将大文件拆分为最小5MB的多个块并行上传,某一块上传失败仅需重传该块即可,无需重新上传整个文件,AWS SDK 2.x自带TransferManager工具类可以直接实现分片上传,七彩云对象存储最大支持50TB的单文件分片上传。
Q2:能不能直接上传前端传来的文件流,不用先保存到本地?
完全可以,putObject方法支持传入InputStream类型的参数,适合Web场景下直接将用户上传的文件流转存到对象存储,无需临时存储到服务器本地磁盘,示例代码如下:
```java
// inputStream为前端上传的文件流,contentLength为文件长度
PutObjectResponse response = s3Client.putObject(request, RequestBody.fromInputStream(inputStream, contentLength));
```
Q3:为什么上传的图片在浏览器打开会直接下载而不是预览?
是因为文件的Content-Type设置错误,SDK会自动根据文件后缀识别Content-Type,如果识别不准确可以在构建上传请求时手动指定,例如:
```java
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucketName)
.key(objectKey)
.contentType("image/jpeg") // 手动指定为图片类型
.build();
```
Q4:AccessKey直接写在代码里不安全怎么办?
不要将AccessKey硬编码到代码或配置文件中,可以将其存储在环境变量、配置中心或者云服务的密钥管理服务中,程序运行时动态读取即可,生产环境一定要注意凭证的权限控制,仅给账号分配必要的桶操作权限。
八、总结
整个上传流程可以归纳为四个核心环节:首先准备S3兼容存储服务的访问凭证和开发环境,其次导入AWS S3 Java SDK依赖,然后初始化S3客户端并调用上传接口,最后验证上传结果即可。
新手初期可以先用小文件测试普通上传功能,跑通流程后再根据业务需求扩展分片上传、断点续传、自定义权限等功能,国内用户优先选择兼容S3的本地对象存储服务例如七彩云对象存储,可以大幅降低接入成本和运维复杂度,提升访问速度和稳定性。另外需要注意,生产环境一定要做好访问凭证的安全管理,避免泄露造成数据安全问题。
需要稳定、兼容 S3 的对象存储?
七彩云对象存储适合图片、视频、大文件下载、静态资源托管和开发者接入。
访问七彩云官网