在之前 SpringBoot(十二)文件上传 文章中,已经学习了使用 SpringBoot 基础的功能,完成静态资源的管理,本片文章我们同样也是对非结构化的静态数据进行管理,不过这次我们使用的是比较常用的 OSS 服务,废话不说,我们一起开始 OSS 之旅吧
什么是 OSS
OSS 是一种面向海量数据规模的分布式存储服务,具有稳定,可靠,安全,低成本的特点。主要用来存储各种非结构化的数据,比如视频,图像,日志,文本文件等。OSS 服务提供标准的 RESTful API 接口,并提供一些常用语言的 SDK 包,方便开发者进行快速开发和二次处理
常用的 OSS
市面上提供云服务的厂商有很多,这里以阿里云的 OSS 服务为主来,完成 OSS 相关的学习和实践
依赖
| 12
 3
 4
 5
 6
 
 | <dependency>
 <groupId>com.aliyun.oss</groupId>
 <artifactId>aliyun-sdk-oss</artifactId>
 <version>3.11.1</version>
 </dependency>
 
 | 
OSS 工具类
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 
 | 
 
 
 
 
 @Slf4j
 public class OssUtils {
 
 
 private static final String ENDPOINT = "xxxxx";
 
 private static final String BUCKET_NAME = "xxxxx";
 
 private static final String ACCESS_KEY_ID = "xxxxx";
 
 private static final String ACCESS_KEY_SECRET = "xxxxx";
 
 
 
 
 
 
 
 public static String uploadFileByFile(File file) {
 
 
 
 
 
 URL url;
 String urlStr = null;
 String[] split = new String[0];
 try {
 OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
 
 String fileName = file.getName();
 ossClient.putObject(BUCKET_NAME, fileName, file);
 
 url = ossClient.generatePresignedUrl(BUCKET_NAME, fileName, new Date(System.currentTimeMillis() + 3600 * 24 * 365 * 10));
 log.info("原始图片地址:{}", url);
 urlStr = url.toString();
 
 
 
 
 
 
 } catch (Exception e) {
 log.warn(e.getMessage());
 }
 return urlStr;
 }
 
 
 
 
 
 
 
 
 public static String uploadFileByByte(byte[] binaryBytes, String fileName) {
 InputStream inputStream = new ByteArrayInputStream(binaryBytes);
 return uploadFileByInputStream(inputStream, fileName);
 }
 
 
 
 
 
 
 
 
 public static String uploadFileByInputStream(InputStream inputStream, String fileName) {
 URL url;
 String urlStr = null;
 String[] split = new String[0];
 try {
 OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
 
 ossClient.putObject(BUCKET_NAME, fileName, inputStream);
 
 url = ossClient.generatePresignedUrl(BUCKET_NAME, fileName, new Date(System.currentTimeMillis() + 3600 * 24 * 365 * 10));
 log.info("原始图片地址:{}", url);
 urlStr = url.toString();
 
 
 
 
 
 
 } catch (Exception e) {
 log.warn(e.getMessage());
 }
 return urlStr;
 }
 
 }
 
 | 
上传
这里我们写一个上传接口
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | @ApiOperation("文件上传", notes = "支持多图上传")@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
 public List<String> uploadTest(@RequestParam("file") List<MultipartFile> file) {
 List<String> uploadList = new ArrayList<>(file.size());
 file.forEach(t -> {
 try {
 String url = OssUtils.uploadFileByInputStream(t.getInputStream(), t.getOriginalFilename());
 uploadList.add(url);
 } catch (IOException e) {
 e.printStackTrace();
 }
 });
 return uploadList;
 }
 
 | 
测试
不废话了,直接看图就好了

问题
- 对于上传获取到的文件地址是一个会过期的地址,并不是一个固定不变的地址,如上截图所示,我偷懒直接将地址链接出的相关参数删去,拿到了一个永久存储的访问连接地址。但这里需要注意,这需要在你的 OSS 管理后台去设置你的文件存储的过期策略。这里就不进行截图演示了(主要是我没有登录系统的账号密码,逃 ~)
- 对于上传的文件我没有自定义文件名,这里有个问题是当用户上传 OSS 服务中已经存在的文件名的文件时,新上传的会覆盖旧文件,因此这个地方需要根据实际的业务场景选择合适的方式。在 OssUtils 工具类中我已经注释掉了将文件名重命名的代码,你可以在此处按照你的业务进行更改
- 第三个问题就是结合上面的两点的汇总方案,其实呢,对于一般的系统,这些静态资源就存永久的连接地址即可。但目前新的系统对用户的资料等也有了 “稍微” 高一点的保护,就是这些资源都是有时效性的,获取的地址就是我们上传拿到的原始地址,而我们存放在数据库中当然也不会是之前那种永久的连接地址,而是对应图片的一个唯一标识信息(可以是重命名后的文件名或者其他能够唯一标识资源你的字段),然后用户访问这些资源时,用存放在数据库中的唯一标识去 OSS 服务上查询对应的资源,然后加载这个地址去显示。
参考
- 阿里云对象存储 OSS
- 对象存储 Kodo
- 华为云对象存储服务 OBS