OSS文件上传(一):简单上传
·
在现代 Web 应用中,文件上传是核心功能之一,而当面对大文件(如视频、压缩包等)时,传统的单文件上传方案往往会遇到超时、网络波动失败、效率低下等问题。阿里云 OSS(Object Storage Service)作为稳定可靠的对象存储服务,提供了完善的文件上传解决方案。本文将从基础的简单上传讲起,逐步深入到分片上传,并结合 Redis 实现断点续传功能,深入剖析OSS文件上传功能,帮助你构建高效、稳定的大文件上传系统。
OSS 文件上传基础:简单上传
简单上传适用于小文件场景(通常建议文件大小≤100MB),通过 OSS 的PutObject接口直接将文件上传到 OSS。这种方式实现简单,适合快速集成。
1. 环境准备
(1)依赖配置(Maven)
首先在pom.xml中添加 OSS SDK 相关依赖:
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
如果使用的是Java 9及以上的版本,则需要添加以下JAXB相关依赖:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
(2)OSS 配置
在application.yml中配置 OSS 连接信息:
aliyun:
oss:
endpoint: oss-cn-beijing.aliyuncs.com # 地域Endpoint
access-key-id: your-access-key-id
access-key-secret: your-access-key-secret
bucket-name: your-bucket-name # 存储桶名称
创建配置类初始化 OSS 客户端:
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "aliyun")
public class AliYunConfig {
private String accessKey; // 阿里云AccessKeyId
private String accessKeySecret; // 阿里云AccessKeySecret
private String ossBucket; // 存储桶名称
private String ossEndpoint; // OSS地域节点
@Bean
public OSS oSSClient() {
return new OSSClient(ossEndpoint, accessKey, accessKeySecret);
}
}
创建统一结果返回类:
package com.netflow.utils;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* 统一结果返回类
* @param <T> 返回数据的类型
*/
public class Msg<T> implements Serializable {
private static final long serialVersionUID = 1L;
// 状态码
private int code;
// 消息
private String message;
// 返回数据
private T data;
// 时间戳
private long timestamp;
// 附加数据(可选)
private Map<String, Object> extra;
// 构造方法
private Msg() {
this.timestamp = System.currentTimeMillis();
}
private Msg(int code, String message) {
this();
this.code = code;
this.message = message;
}
private Msg(int code, String message, T data) {
this(code, message);
this.data = data;
}
// 成功静态工厂方法
public static <T> Msg<T> success() {
return new Msg<>(200, "操作成功");
}
public static <T> Msg<T> success(String message) {
return new Msg<>(200, message);
}
public static <T> Msg<T> success(T data) {
return new Msg<>(200, "操作成功", data);
}
public static <T> Msg<T> success(String message, T data) {
return new Msg<>(200, message, data);
}
// 失败静态工厂方法
public static <T> Msg<T> fail() {
return new Msg<>(500, "操作失败");
}
public static <T> Msg<T> fail(String message) {
return new Msg<>(500, message);
}
public static <T> Msg<T> fail(int code, String message) {
return new Msg<>(code, message);
}
// 链式调用方法
public Msg<T> code(int code) {
this.code = code;
return this;
}
public Msg<T> message(String message) {
this.message = message;
return this;
}
public Msg<T> data(T data) {
this.data = data;
return this;
}
public Msg<T> extra(String key, Object value) {
if (this.extra == null) {
this.extra = new HashMap<>();
}
this.extra.put(key, value);
return this;
}
// Getter方法
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public T getData() {
return data;
}
public long getTimestamp() {
return timestamp;
}
public Map<String, Object> getExtra() {
return extra;
}
@Override
public String toString() {
return "Msg{" +
"code=" + code +
", message='" + message + '\'' +
", data=" + data +
", timestamp=" + timestamp +
", extra=" + extra +
'}';
}
}
2. 简单上传实现
简单上传的核心是通过 OSS 客户端的putObject方法直接上传文件流,代码如下:
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.netflow.config.AliYunConfig;
import com.netflow.utils.Msg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@RestController
@Slf4j
public class OSScontroller {
@Autowired
OSS ossClient;
@Autowired
AliYunConfig aliYunConfig;
@PostMapping("/upload")
public Msg<String> uploadFile(@RequestParam("file") MultipartFile file) {
try {
//获取初始文件名
String fileName = file.getOriginalFilename();
//获取文件后缀
String suffixName = fileName.substring(fileName.lastIndexOf("."));
//UUID作为文件名
String newFileName = UUID.randomUUID().toString()+ "-"+ fileName + suffixName;
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(aliYunConfig.getOssBucket(), newFileName, file.getInputStream());
// 上传文件。
PutObjectResult result = ossClient.putObject(putObjectRequest);
return Msg.success("上传成功");
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException | IOException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
return Msg.fail("上传失败");
}
}
3. 简单上传的局限性
简单上传虽然实现简单,但存在明显短板:
- 文件大小限制:单次上传最大支持 5GB(OSS 限制),但实际网络中 1GB 以上文件易失败;
- 无断点续传:网络中断后需重新上传整个文件;
- 效率低:单线程上传,无法利用带宽资源。
因此,对于大文件(建议>100MB),需采用分片上传方案。想要了解分片上传内容的小伙伴可以参考我的另一篇文章
更多推荐



所有评论(0)