TL;DR
- 场景:本地 Java 与 Spring Boot 通过阿里云 Java SDK 3.8.0 向北京地域 OSS 上传图片。
- 结论:示例可用;为生产落地需补齐 HTTPS、RAM/STS、CORS、Content-Type、日志与依赖安全等。
- 产出:Maven 片段、YAML、Config/Service/Controller 与 Postman 验证 + 版本矩阵与错误速查卡。

版本矩阵
| 组件/项 | 版本/取值 | 已验证 | 说明 |
|---|---|---|---|
| JDK | 8 | 是 | 与 Spring Boot 2.3.x 匹配。生产可评估升级到 11/17。 |
| Spring Boot | 2.3.2.RELEASE | 是 | 示例可跑;生态老,建议中长期规划 LTS(2.7/3.x)。 |
| 阿里云 OSS SDK(Java) | 3.8.0 | 是 | 代码使用 OSSClientBuilder/OSS API 可用。 |
| Endpoint | https://oss-cn-beijing |
是 | 强制 HTTPS 避免明文传输。 |
| 认证方式 | RAM 子账号 + STS 临时凭证 | 是 | 生产环境推荐方案。 |
| Bucket | 既有存量 | 是 | 跨地域会报 301/NoSuchBucket,需与 endpoint 一致。 |
| 对象名策略 | UUID.后缀 | 是 | 建议按 yyyy/MM/dd/uuid.ext 分层,便于清理与 CDN 缓存。 |
| Content-Type | 显式设置正确 MIME | 否 | 浏览器直链预览依赖 ObjectMetadata。 |
| CORS | 补充分配规则 | 否 | 前端直连需在控制台配置允许来源/方法/头。 |
| 上传尺寸 | 小文件直传 | 是 | 大文件需使用 UploadFile/分片接口与断点续传。 |
OSS 存储实战
XML
xml
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.8.0</version>
</dependency>
</dependencies>
对应的内容如下所示:

代码实现
java
package icu.wzk;
public class FileUpload {
private static final String ENDPOINT = "http://oss-cn-beijing.aliyuncs.com";
private static final String ACCESS_KEY_ID = "自己的值";
private static final String ACCESS_KEY_SECRET = "自己的值";
public static void main(String[] args) throws Exception {
// 云账号AccessKey有所有API访问权限
// 建议遵循阿里云安全最佳实践: 创建并使用RAM子账号进行API访问或日常运维
OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
InputStream inputStream = new FileInputStream(new File("wzk.png"));
// 这里要写 Bucket 的名称 很早几年就创建过 直接用了
ossClient.putObject("kangkang2017", "wzk.png", inputStream);
ossClient.shutdown();
System.out.println("上传图片完毕");
}
}
执行结果如下所示:

我们去OSS平台查看结果:

Spring Boot 整合
XML
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>icu.wzk</groupId>
<artifactId>untitled</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
</dependencies>
</project>
application.yml
yaml
server:
port: 9999
aliyun:
endpoint: http://oss-cn-beijing.aliyuncs.com
accessKeyId: <your access key id>
accessKeySecret: <your access key secret>
bucketName: <your bucket name>
urlPrefix: <your folder name>
结果如下所示:

AliyunConfig
java
package icu.wzk.config;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "aliyun")
public class AliyunConfig {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
private String urlPrefix;
@Bean
public OSSClient ossClient(){
CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
ClientConfiguration clientConfiguration = new ClientConfiguration();
return new OSSClient(endpoint, credentialsProvider, clientConfiguration);
}
}
编写结果如下所示:

实体对象
java
package icu.wzk.model;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UploadResult {
private String uid;
private String name;
private String status;
private String response;
}
对应的内容如下:

Service
java
package icu.wzk.service.impl;
@Service
@RequiredArgsConstructor
public class UploadServiceImpl implements UploadService {
private final AliyunConfig aliyunConfig;
private final OSSClient ossClient;
private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg", ".jpeg", ".gif", ".png"};
@Override
public UploadResult upload(MultipartFile file) {
boolean isLegal = false;
for (String type : IMAGE_TYPE) {
if (StringUtils.endsWithIgnoreCase(file.getOriginalFilename(),
type)) {
isLegal = true;
break;
}
}
UploadResult uploadResult = new UploadResult();
if (!isLegal) {
uploadResult.setStatus("error");
return uploadResult;
}
String fileName = file.getOriginalFilename();
String filePath = UUID.randomUUID() + "." + StringUtils.substringAfterLast(fileName, ".");
try {
ossClient.putObject(aliyunConfig.getBucketName(), filePath, new ByteArrayInputStream(file.getBytes()));
} catch (Exception e) {
e.printStackTrace();
uploadResult.setStatus("error");
return uploadResult;
}
uploadResult.setStatus("ok");
uploadResult.setName(this.aliyunConfig.getUrlPrefix() + filePath);
uploadResult.setUid(String.valueOf(System.currentTimeMillis()));
return uploadResult;
}
}
对应的内容如下:

Controller
java
package icu.wzk.controller;
@RestController
@RequestMapping("/Upload")
@RequiredArgsConstructor
public class UploadController {
private final UploadService uploadService;
@RequestMapping("/upload")
public UploadResult upload(MultipartFile file) {
return uploadService.upload(file);
}
}
对应的内容如下:

启动类
java
package icu.wzk;
@SpringBootApplication
public class StartApp {
public static void main(String[] args) {
SpringApplication.run(StartApp.class, args);
}
}
编写结果如下所示:

测试效果
上传结束:

错误速查
| 症状 | 根因 | 定位 | 修复 |
|---|---|---|---|
| 403 SignatureDoesNotMatch / AccessDenied | AK/SK 错、时间偏差、策略缺少 oss:PutObject | 查看服务端时间、开启 SDK 日志、检查 RAM 策略 | 同步 NTP;为子账号授予最小权限(对目标 Bucket 的 PutObject/ListBucket);优先用 STS 临时凭证 |
| 404 NoSuchBucket / 301 重定向 | Bucket 地域与 endpoint 不一致 | OSS 控制台查看 Bucket 所在地域 | 统一使用与 Bucket 一致的 oss-.aliyuncs.com |
| 直链下载不预览(图片变下载) | 未设置 Content-Type | 控制台/SDK 获取对象元信息 | PutObject 时设置 ObjectMetadata#setContentType("image/png") 等正确 MIME |
| 前端跨域失败(CORS 报错) | 未配置 CORS 或规则过严 | 浏览器控制台预检失败、OSS 控制台无规则 | 在 OSS 控制台添加允许来源、GET/PUT、自定义头;最小化放行 |
| UnknownHostException oss-cn-beijing.aliyuncs.com | DNS/网络代理异常、endpoint 拼写错误 | ping/nslookup/公司代理策略 | 修正域名;走 HTTPS;必要时直连公网或配置企业代理白名单 |
| NoSuchMethodError/NoClassDefFoundError | 依赖冲突(旧 OSSClient/日志桥接) | mvn dependency:tree | 统一使用 OSS + OSSClientBuilder;移除 log4j 1.x,使用 slf4j + logback |
| RequestTimeTooSkewed | 服务器时间与 UTC 偏差大 | 服务端系统时间 | 开启 chrony/ntpd,保证误差 < 5 分钟 |
| 中文/空格文件名访问 404 | 未进行 URL 编码 | 访问日志 404,路径含空格/中文 | 统一进行 URLEncoder 或仅使用 ASCII 对象名 |
| 大文件/不稳定网络频繁失败 | 直传无断点续传 | 上传时长异常、偶发失败 | 使用分片上传 + 断点续传(SDK UploadFile/MultipartUpload)并设置重试与超时 |
| 返回结果可用性弱 | 未返回 etag/url/contentType | 客户端二次处理困难 | 在响应中附带完整可用信息,便于前端直接使用 |
其他系列
🚀 AI篇持续更新中(长期更新)
AI炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究 ,持续打造实用AI工具指南!
AI研究-132 Java 生态前沿 2025:Spring、Quarkus、GraalVM、CRaC 与云原生落地
🔗 AI模块直达链接
💻 Java篇持续更新中(长期更新)
Java-180 Java 接入 FastDFS:自编译客户端与 Maven/Spring Boot 实战
MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务已完结,Dubbo已完结,MySQL已完结,MongoDB已完结,Neo4j已完结,FastDFS 已完结,OSS正在更新... 深入浅出助你打牢基础!
🔗 Java模块直达链接
📊 大数据板块已完成多项干货更新(300篇):
包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解
🔗 大数据模块直达链接