一、开场白:后端为啥绕不开对象存储?
上次产品经理拍我肩膀:"用户要传 10G 的设计图,你数据库存一下?"我当场掏出对象存储的 "户口本":这玩意儿才是文件的 "云端豪宅"------ 比本地存储能扛,比数据库能装,还自带 CDN 加速 buff。今天咱从入门到炫技,把对象存储扒得明明白白!
二、对象存储:不是 "文件夹" 的 "文件柜"
先给萌新划重点:对象存储(OSS/S3)≠ 本地文件夹它是把文件拆成 "对象"(包含数据 + 元信息),存在分布式集群里,就像小区的智能快递柜:
- 优势:抗造(多副本存储)、能装(PB 级容量)、省钱(按使用量付费)
- 场景:图片 / 视频存储、日志备份、用户文件上传(后端 er 的日常刚需)
三、实战 1:阿里云 OSS 简单上传(5 分钟上手版)

别翻官方文档了,我把 "废话" 都删了,直接上 Java 版干货代码:
1. 先搭环境(Maven 依赖)
xml
xml
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
2. 核心上传代码(像寄快递一样简单)
java
public class OssSimpleUpload {
// 密钥别硬编码!放配置文件里!(踩坑提醒)
private static final String ENDPOINT = "oss-cn-beijing.aliyuncs.com";
private static final String ACCESS_KEY = "你的AK";
private static final String SECRET_KEY = "你的SK";
private static final String BUCKET_NAME = "你的桶名";
public static void uploadFile(File file) {
// 1. 连接OSS客户端
OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY, SECRET_KEY);
try {
// 2. 上传(桶名+文件路径+文件)
ossClient.putObject(BUCKET_NAME, "user-uploads/" + file.getName(), new FileInputStream(file));
// 3. 拿访问链接(有效期1小时)
Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
String url = ossClient.generatePresignedUrl(BUCKET_NAME, "user-uploads/" + file.getName(), expiration).toString();
System.out.println("文件上传成功!链接:" + url);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 一定要关客户端!不然连接泄漏(血的教训)
ossClient.shutdown();
}
}
}
踩坑提醒:
- 桶权限别设 "公有读"!不然路人能下载你家文件
- 密钥用 RAM 子账号!给最小权限(只给上传权限)
四、大文件上传:直接传?怕不是要被测试小姐姐打
用户传个 2G 的视频,直接调用上面的代码?结果:网络一波动就断,重传又要从头来,前端还报超时 ------ 这就是 "大文件上传噩梦"。解法:分片上传!把大文件切成 "小蛋糕",一块一块传,断了只补缺的。
五、分片上传:三步搞定 "大文件搬运"

以 100MB 文件为例,切成 10MB / 片,流程像拼乐高:
第一步:分片(前端切,后端躺平)
前端用File.slice()
切分,比如:
javascript
arduino
// 10MB一片(10*1024*1024字节)
const chunkSize = 10 * 1024 * 1024;
const chunks = Math.ceil(file.size / chunkSize);
// 切第一片:file.slice(0, chunkSize)
第二步:上传分片(带 "编号" 和 "身份证")
每个分片要带 3 个关键信息:
fileMd5
:整个文件的哈希值(后面判重有用)chunkIndex
:分片编号(0,1,2...)totalChunks
:总分片数
后端接收后,先存到临时文件夹,比如/tmp/oss-chunks/${fileMd5}/${chunkIndex}
第三步:合并分片(OSS 帮你干活)
所有分片传完,调用 OSS 的completeMultipartUpload
接口合并:
java
java
public void mergeChunks(String fileMd5, String fileName, int totalChunks) {
OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY, SECRET_KEY);
// 1. 初始化分片上传
InitiateMultipartUploadResult initResult = ossClient.initiateMultipartUpload(
new InitiateMultipartUploadRequest(BUCKET_NAME, "user-uploads/" + fileName)
);
String uploadId = initResult.getUploadId();
// 2. 准备分片列表(按编号排序!)
List<PartETag> partETags = new ArrayList<>();
for (int i = 0; i < totalChunks; i++) {
// 从临时文件夹读分片,上传到OSS
UploadPartResult uploadResult = ossClient.uploadPart(
new UploadPartRequest()
.withBucketName(BUCKET_NAME)
.withKey("user-uploads/" + fileName)
.withUploadId(uploadId)
.withPartNumber(i + 1) // 分片编号从1开始
.withInputStream(new FileInputStream("/tmp/oss-chunks/" + fileMd5 + "/" + i))
);
partETags.add(uploadResult.getPartETag());
}
// 3. 通知OSS合并
ossClient.completeMultipartUpload(
new CompleteMultipartUploadRequest(BUCKET_NAME, "user-uploads/" + fileName, uploadId, partETags)
);
ossClient.shutdown();
// 4. 删临时文件(别占空间!)
FileUtils.deleteDirectory(new File("/tmp/oss-chunks/" + fileMd5));
}
六、灵魂拷问 1:怎么避免重复上传同一个文件?
用户手抖传了 3 次同个视频,总不能存 3 份吧?用 "文件身份证"MD5
搞定:
流程:
-
前端选文件后,先算整个文件的 MD5(大文件可分片算 MD5 再合并,避免卡屏)
-
上传前先调后端接口:
/check-file?md5=xxx
-
后端查数据库(存 "MD5 - 文件路径" 映射):
- 有记录:直接返回已存的文件链接,不上传了
- 没记录:返回 "可以上传",走分片流程
优化技巧:
OSS 的ETag
字段也能当 "简易 MD5",但大文件分片后 ETag 会变,还是自己存 MD5 靠谱。
七、灵魂拷问 2:怎么防恶意文件(木马 / 病毒)?
用户传个xxx.jpg.exe
,后端直接存?服务器要遭殃!三重校验安排上:
1. 第一层:文件头校验(查 "身份证照片")
不是看后缀名!看文件二进制开头的 "魔法数字":
java
java
// 校验是否为图片(JPG/PNG/GIF)
public boolean checkFileHeader(File file) {
byte[] header = new byte[8];
try (FileInputStream fis = new FileInputStream(file)) {
fis.read(header);
String headerHex = bytesToHex(header);
// JPG开头:FFD8FF,PNG开头:89504E47,GIF开头:47494638
return headerHex.startsWith("FFD8FF") || headerHex.startsWith("89504E47") || headerHex.startsWith("47494638");
} catch (Exception e) {
return false;
}
}
2. 第二层:内容检测(翻 "包" 检查)
用工具扫文件内容,比如:
- 开源工具:ClamAV(扫病毒)
- 云服务:阿里云 OSS 内容安全(直接集成,扫色情 / 暴力 / 木马)
3. 第三层:权限隔离(设 "隔离区")
- 上传的文件先存到 "临时桶",校验通过再移到 "正式桶"
- 正式桶禁止执行权限(比如给文件加
Content-Disposition: attachment
,强制下载不执行)
八、总结:后端 er 的 "文件上传生存指南"
- 小文件:直接 OSS 简单上传(别瞎搞分片)
- 大文件:分片上传三步走(切分→传片→合并)
- 防重复:MD5 前置校验(省空间省流量)
- 防恶意:文件头 + 内容检测 + 权限隔离(保命三件套)
最后问一句:你踩过哪些文件上传的坑?评论区分享下,让我乐呵乐呵~
这篇博客兼顾了技术深度和阅读趣味,符合掘金用户的偏好。你若觉得某部分代码不够详细、想加前端分片示例,或要调整风趣程度,随时跟我说!