oss

工作中需要用到文件上传,之前使用的是本地文件系统存储方式,后来重构为支持多个存储源的方式,目前支持三种方式:local、seaweedfs、minio

存储介质

seaweedfs

seaweedfs是一款go语言开发的轻量级、高性能的存储服务器。

https://github.com/chrislusf/seaweedfs

  1. # 启动 master
  2. docker run -d \
  3. -p 9333:9333 \
  4. -p 19333:19333 \
  5. -v /home/mining/report-cloud/docker/seaweedfs/master/data:/data \
  6. --name seaweedfs-master \
  7. chrislusf/seaweedfs:1.53 \
  8. master -ip=master
  9. # 启动 volume
  10. docker run -d \
  11. -p 8080:8080 \
  12. -p 18080:18080 \
  13. -v /home/mining/report-cloud/docker/seaweedfs/volume01/data:/data \
  14. --name seaweedfs-volume \
  15. --link seaweedfs-master:master \
  16. chrislusf/seaweedfs:1.53 \
  17. volume -max=5 -mserver="master:9333" -port=8080

访问web地址:http://localhost:9333/

简单使用:

  1. # 申请空间
  2. curl http://localhost:9333/dir/assign
  3. #
  4. {"count":1,"fid":"4,017f52110b","url":"127.0.0.1:8080","publicUrl":"localhost:80
  5. 80"}
  6. # 推送文件,4,017f52110b表示第4个volume,017f52110b表示文件的唯一标识
  7. curl -F file=@/home/seaweedfs/balance.png http://127.0.0.1:8080/4,017f52110b

minio

MinIO是与Amazon S3 API兼容的高性能对象存储服务器,提供了人性化的管理页面

https://github.com/minio/minio

  1. docker run --name report-minio \
  2. -p 19000:9000 \
  3. -e "MINIO_ACCESS_KEY=qweasdzxc" \
  4. -e "MINIO_SECRET_KEY=1234567890" \
  5. -v /home/mining/report-cloud/docker/minio:/data \
  6. -d minio/minio:latest server /data
  7. # web 管理页面
  8. http://localhost:19000/minio/login
  9. # 创建一个 bucket 为 report
  10. # 通过URL直接访问文件需要设置权限,参考下面博客
  11. # https://blog.csdn.net/iKaChu/article/details/105809957
  12. # 访问格式为
  13. http://localhost:19000/bucket名/对象名

Java代码

maven依赖

  1. <!-- oss 存储的依赖 -->
  2. <!-- seaweedfs 依赖 -->
  3. <dependency>
  4. <groupId>org.lokra.seaweedfs</groupId>
  5. <artifactId>seaweedfs-client</artifactId>
  6. <version>0.7.3.RELEASE</version>
  7. </dependency>
  8. <!-- minio 依赖 -->
  9. <dependency>
  10. <groupId>io.minio</groupId>
  11. <artifactId>minio</artifactId>
  12. <version>3.0.10</version>
  13. </dependency>

代码

配置类

FileTag 枚举类

用来标记使用哪种存储介质

  1. /**
  2. * 文件上传的tag
  3. */
  4. public enum FileTag {
  5. TYPE_LOCAL,
  6. TYPE_MINIO ,
  7. TYPE_SEAWEEDFS;
  8. }

FileUploadConfigLocal

本地存储配置类

  1. public class FileUploadConfigLocal {
  2. private String parentPath;
  3. // 省略 get set
  4. }

FileUploadConfigSeaweedfs

seaweedfs存储配置类

  1. public class FileUploadConfigSeaweedfs {
  2. private String host;
  3. private int port = 9333;
  4. private String publicUrl;
  5. private int connectTimeout = 60; // 60 s
  6. // 省略 get set
  7. }

FileUploadConfigMinio

minio存储配置类

  1. public class FileUploadConfigMinio {
  2. private String domain; // url 前缀
  3. private String accesKey;
  4. private String secretKey;
  5. private String bucket; // 必须事先创建好
  6. // 省略 get set
  7. }

FileUploadConfig

spring application.yaml 配置类

  1. import org.springframework.boot.context.properties.ConfigurationProperties;
  2. @ConfigurationProperties( prefix = "oss-config")
  3. public class FileUploadConfig {
  4. FileTag tag;
  5. FileUploadConfigLocal local;
  6. FileUploadConfigSeaweedfs seaweedfs;
  7. FileUploadConfigMinio minio;
  8. // 省略 get set
  9. }

配置文件

application.yaml

  1. # 对象存储配置
  2. oss-config:
  3. tag: TYPE_LOCAL # 使用哪种存储介质
  4. local:
  5. parent-path: D:\dev\2019-06-19\upload
  6. minio:
  7. domain: http://localhost:19000
  8. bucket: report
  9. acces-key: qweasdzxc
  10. secret-key: 1234567890
  11. seaweedfs:
  12. host: localhost
  13. port: 9333
  14. publicUrl: http://localhost:8080
  15. connectTimeout: 3000 # 5min

FileUploadInfoVO文件上传类

  1. public class FileUploadInfoVO {
  2. private String fileName; // 文件名
  3. private String suffix; // 文件后缀
  4. private String contentType; // 文件类型
  5. private Long size; // 文件大小
  6. private String fid; // 文件唯一ID,同时也是保存在服务器上的文件名
  7. private boolean delete; // 是否删除,默认false
  8. private String description;
  9. private String url; // 完整的url
  10. private String tag; // 标签,比如
  11. private String uploadTime;
  12. private String deleteTime;
  13. // 省略 get set
  14. }

业务逻辑类

FileStorageService 文件存储接口

  1. /**
  2. * 文件存储的接口
  3. */
  4. public interface FileStorageService {
  5. FileUploadInfoVO upload(InputStream in, FileUploadInfoVO fileUploadInfoVO) throws Exception ;
  6. FileUploadInfoVO upload(byte[] bytes, FileUploadInfoVO fileUploadInfoVO) throws Exception ;
  7. FileUploadInfoVO delete(FileUploadInfoVO fileUploadInfoVO) throws Exception ;
  8. }

本地存储实现

  1. @Service("FileStorageServiceLocal")
  2. public class FileStorageServiceLocal implements FileStorageService {
  3. @Autowired
  4. FileUploadConfig fileUploadConfig;
  5. @PostConstruct
  6. public void init() {
  7. FileUtils.checkAndCreateDir(fileUploadConfig.getLocal().getParentPath());
  8. }
  9. @Override
  10. public FileUploadInfoVO upload(InputStream in, FileUploadInfoVO fileUploadInfoVO) throws Exception {
  11. String filePath = fileUploadConfig.getLocal().getParentPath() + File.separator + fileUploadInfoVO.getFid();
  12. FileUtils.copyFileFromInputStream(in, filePath);
  13. fileUploadInfoVO.setUrl(filePath+"."+fileUploadInfoVO.getSuffix());
  14. return fileUploadInfoVO;
  15. }
  16. @Override
  17. public FileUploadInfoVO upload(byte[] bytes, FileUploadInfoVO fileUploadInfoVO) throws Exception {
  18. String filePath = fileUploadConfig.getLocal().getParentPath() + File.separator + fileUploadInfoVO.getFid();
  19. FileUtils.copyFileFromBytes(bytes, filePath);
  20. fileUploadInfoVO.setUrl(filePath);
  21. return fileUploadInfoVO;
  22. }
  23. @Override
  24. public FileUploadInfoVO delete(FileUploadInfoVO fileUploadInfoVO) throws Exception {
  25. File file = new File(fileUploadInfoVO.getUrl());
  26. if(file.exists()) {
  27. file.delete();
  28. }
  29. return fileUploadInfoVO;
  30. }
  31. }

Seaweedfs存储实现

  1. @Service("FileStorageServiceSeaweedfs")
  2. public class FileStorageServiceSeaweedfs implements FileStorageService {
  3. @Autowired
  4. FileUploadConfig fileUploadConfig;
  5. FileTemplate fileTemplate;
  6. @PostConstruct
  7. public void init() {
  8. FileUploadConfigSeaweedfs seaweedfs = fileUploadConfig.getSeaweedfs();
  9. FileSource fileSource = new FileSource();
  10. fileSource.setHost(seaweedfs.getHost());
  11. fileSource.setPort(seaweedfs.getPort());
  12. fileSource.setConnectionTimeout(seaweedfs.getConnectTimeout());//5min
  13. try {
  14. fileSource.startup();
  15. } catch (IOException e) {
  16. throw new RuntimeException("创建seaweedfs连接失败,原因是:" + e.getMessage());
  17. }
  18. fileTemplate = new FileTemplate(fileSource.getConnection(), seaweedfs.getPublicUrl());
  19. }
  20. @Override
  21. public FileUploadInfoVO upload(InputStream in, FileUploadInfoVO fileUploadInfoVO) throws Exception {
  22. FileHandleStatus fileHandleStatus = fileTemplate.saveFileByStream(fileUploadInfoVO.getFileName(), in, ContentType.create(fileUploadInfoVO.getContentType(), "utf-8"));
  23. fileUploadInfoVO.setFid(fileHandleStatus.getFileId());
  24. fileUploadInfoVO.setUrl(String.format("%s/%s", fileUploadConfig.getSeaweedfs().getPublicUrl(), fileHandleStatus.getFileId()));
  25. return fileUploadInfoVO;
  26. }
  27. @Override
  28. public FileUploadInfoVO upload(byte[] bytes, FileUploadInfoVO fileUploadInfoVO) throws Exception {
  29. return upload(new ByteArrayInputStream(bytes), fileUploadInfoVO);
  30. }
  31. @Override
  32. public FileUploadInfoVO delete(FileUploadInfoVO fileUploadInfoVO) throws Exception {
  33. fileTemplate.deleteFile(fileUploadInfoVO.getFid());
  34. return fileUploadInfoVO;
  35. }
  36. }

Minio存储实现

  1. @Service("FileStorageServiceMinio")
  2. public class FileStorageServiceMinio implements FileStorageService {
  3. @Autowired
  4. FileUploadConfig fileUploadConfig;
  5. @Override
  6. public FileUploadInfoVO upload(InputStream in, FileUploadInfoVO fileUploadInfoVO) throws Exception {
  7. FileUploadConfigMinio minio = fileUploadConfig.getMinio();
  8. String domain = minio.getDomain();
  9. String bucket = minio.getBucket();
  10. String fileName = fileUploadInfoVO.getFileName();
  11. MinioClient minioClient = new MinioClient(domain, minio.getAccesKey(), minio.getSecretKey());
  12. minioClient.putObject("report", fileName, in, fileUploadInfoVO.getSize(), fileUploadInfoVO.getContentType());
  13. fileUploadInfoVO.setUrl(String.format("%s/%s/%s", domain, bucket, fileName));
  14. return fileUploadInfoVO;
  15. }
  16. @Override
  17. public FileUploadInfoVO upload(byte[] bytes, FileUploadInfoVO fileUploadInfoVO) throws Exception {
  18. return upload(new ByteArrayInputStream(bytes), fileUploadInfoVO);
  19. }
  20. @Override
  21. public FileUploadInfoVO delete(FileUploadInfoVO fileUploadInfoVO) throws Exception {
  22. FileUploadConfigMinio minio = fileUploadConfig.getMinio();
  23. MinioClient minioClient = new MinioClient(minio.getDomain(), minio.getAccesKey(), minio.getSecretKey());
  24. minioClient.removeObject(minio.getBucket(), fileUploadInfoVO.getFileName());
  25. return fileUploadInfoVO;
  26. }
  27. }

存储工厂类实现

用来根据 FileTag 枚举类获得对应的具体实现

  1. @Service
  2. public class FileStorageFactory {
  3. Map<FileTag, FileStorageService> fileStorageServiceMap;
  4. @Qualifier("FileStorageServiceLocal")
  5. @Autowired
  6. FileStorageService fileStorageServiceLocal;
  7. @Qualifier("FileStorageServiceSeaweedfs")
  8. @Autowired
  9. FileStorageService fileStorageServiceSeaweedfs;
  10. @Qualifier("FileStorageServiceMinio")
  11. @Autowired
  12. FileStorageService fileStorageServiceMinio;
  13. @PostConstruct
  14. public void init() {
  15. fileStorageServiceMap = new HashMap<>();
  16. fileStorageServiceMap.put(FileTag.TYPE_LOCAL, fileStorageServiceLocal);
  17. fileStorageServiceMap.put(FileTag.TYPE_SEAWEEDFS, fileStorageServiceSeaweedfs);
  18. fileStorageServiceMap.put(FileTag.TYPE_MINIO, fileStorageServiceMinio);
  19. }
  20. public FileStorageService get(FileTag type) {
  21. FileStorageService fileStorageService = fileStorageServiceMap.get(type);
  22. return fileStorageService == null ? fileStorageServiceMap.get(FileTag.TYPE_LOCAL) : fileStorageService;
  23. }
  24. }

业务中实现

这里根据具体的业务,来选择具体的实现逻辑

eg:

  1. @Autowired
  2. private FileStorageFactory fileStorageFactory;
  3. public FileUploadInfoVO put(MultipartFile multipartFile) throws Exception {
  4. FileUploadInfoVO vo = new FileUploadInfoVO();
  5. // 填充一些信息(省略)
  6. // 获得文件上传处理器
  7. FileStorageService fileStorageService = fileStorageFactory.get(FileTag.TYPE_LOCAL);
  8. fileUploadInfoVO = fileStorageService.upload(multipartFile.getInputStream(), vo);
  9. // ... 业务逻辑
  10. }

这样,配置文件中可以使用FileTag来控制文件存储的介质,从而实现一个简单的对象存储服务器。

java实现简单的oss存储的更多相关文章

  1. Java使用阿里云OSS对象存储上传图片

    原 Java使用阿里云OSS对象存储上传图片 2017年03月27日 10:47:28 陌上桑花开花 阅读数 26804更多 分类专栏: 工作案例总结 版权声明:本文为博主原创文章,遵循CC 4.0 ...

  2. Java项目接入阿里云OSS存储

    需求背景 目前公司内部项目所支持的文件云存储方式还是公司内部项目组提供的方案,但在时间的考验之下,弊端显现,尤其是灾备切换过程中需要切换访问地址,这种操作不方便,更可能因为中间过程的失误导致资源不可用 ...

  3. java实现简单的单点登录

    java实现简单的单点登录 摘要:单点登录(SSO)的技术被越来越广泛地运用到各个领域的软件系统当中.本文从业务的角度分析了单点登录的需求和应用领域:从技术本身的角度分析了单点登录技术的内部机制和实现 ...

  4. 编写你的第一个 Java 版 Raft 分布式 KV 存储

    前言 本文旨在讲述如何使用 Java 语言实现基于 Raft 算法的,分布式的,KV 结构的存储项目.该项目的背景是为了深入理解 Raft 算法,从而深刻理解分布式环境下数据强一致性该如何实现:该项目 ...

  5. BerkeleyDB java的简单使用

    关于BerkeleyDB的有点和优点,列在以下 JE offers the following major features: Large database support. JE databases ...

  6. java实现简单窗体小游戏----球球大作战

    java实现简单窗体小游戏----球球大作战需求分析1.分析小球的属性: ​ 坐标.大小.颜色.方向.速度 2.抽象类:Ball ​ 设计类:BallMain—创建窗体 ​ BallJPanel—画小 ...

  7. 用Java实现简单的区块链

    用 Java 实现简单的区块链 1. 概述 本文中,我们将学习区块链技术的基本概念.也将根据概念使用 Java 来实现一个基本的应用程序. 进一步,我们将讨论一些先进的概念以及该技术的实际应用. 2. ...

  8. Java集合简单介绍

    再最前面分享一下我再学习集合时的方法: 1.首先了解各集合的定义和特点 2.集合的构造方法和常用方法(增删改查等) 3.了解集合使用的场景,再什么情况下使用什么类型的集合(关键是集合的特性) 4.了解 ...

  9. 谷粒 | 10 | 阿里云OSS存储对象服务

    阿里云OSS对象存储服务 准备工作 1.在service模块新建子模块service_oss 2.引入pom.xml文件中引入oss服务依赖 <dependencies> <!--a ...

随机推荐

  1. CentOS 7.1 图形化安装

    1.在命令行下输入下面的命令来安装 Gnome 包 sudo  yum groupinstall "GNOME Desktop" "Graphical Administr ...

  2. R的安装以及包安装

        今天看论文,需要用到R语言的库,于是又折腾了半天..     其实并没有什么太大的问题,只是在第三方包的下载方面还有python中使用R方面遇到了问题: 第三方包的导入      其实在网上有 ...

  3. 学习ASP.NET Core(06)-Restful与WebAPI

    上一篇我们使用Swagger添加了接口文档,使用Jwt完成了授权,本章我们简答介绍一下RESTful风格的WebAPI开发过程中涉及到的一些知识点,并完善一下尚未完成的功能 .NET下的WebAPI是 ...

  4. node的fs模块

    node的file system模块提供的api有同步和异步两种模式(大多数情况下都是用的异步方法,毕竟异步是node的特色,至于提供同步方法,可能应用程序复杂的时候有些场景使用同步会比较合适).异步 ...

  5. RN概述

    一.RN概述 中文网:http://reactnative.cn/ ReactNative:使用JS语法编写移动APP应用,RN会把JS转换为底层Java或OC, 最终运行于手机-------完全不依 ...

  6. JSP+SSM+Mysql实现的图书馆预约占座管理系统

    项目简介 项目来源于:https://gitee.com/gepanjiang/LibrarySeats 因原gitee仓库无数据库文件且存在水印,经过本人修改,现将该仓库重新上传至个人gitee仓库 ...

  7. [ES6系列-06]展开操作符 Spread Operator 就像解压到这里

    [原创]码路工人 Coder-Power 大家好,这里是码路工人有力量,我是码路工人,你们是力量. github-pages 博客园cnblogs 在前面的文章中,介绍了...在获取剩余参数中的作用. ...

  8. word修改页眉使本页的页眉与别的页不一样

    关键回答:双击要修改的页的页眉,word顶端的工具栏“页面设置”当中的“链接到前一个”选项不要选中,即可修改本页页眉使之与别的页不一样. 详见:https://iask.sina.com.cn/b/2 ...

  9. Function's dict

    众所周知,Python是没有switch的,那么只能使用 if else来进行判断,但是if else比较冗长, 使用太多的if else 代码看起来不简洁,如下 student.py def stu ...

  10. ISTQB认证测试工程师基础大纲(2019.12.25)

    1.本文档目的: 用于生成认证测试员基础级考试题. 本大纲中除了简介和附录外,考核通常包含了所有K1级别的内容,因此,应试者可能会被考到本大纲中要求识别,牢记,或记忆的关键词或概念.在本大纲中,每章开 ...