在之前 SpringBoot(十二)文件上传 文章中,已经学习了使用 SpringBoot 基础的功能,完成静态资源的管理,本片文章我们同样也是对非结构化的静态数据进行管理,不过这次我们使用的是比较常用的 OSS 服务,废话不说,我们一起开始 OSS 之旅吧
什么是 OSS
OSS 是一种面向海量数据规模的分布式存储服务,具有稳定,可靠,安全,低成本的特点。主要用来存储各种非结构化的数据,比如视频,图像,日志,文本文件等。OSS 服务提供标准的 RESTful API 接口,并提供一些常用语言的 SDK 包,方便开发者进行快速开发和二次处理
常用的 OSS
市面上提供云服务的厂商有很多,这里以阿里云的 OSS 服务为主来,完成 OSS 相关的学习和实践
依赖
1 2 3 4 5 6
| <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.11.1</version> </dependency>
|
OSS 工具类
1 2 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; }
}
|
上传
这里我们写一个上传接口
1 2 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