oss

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

存储介质

seaweedfs

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

https://github.com/chrislusf/seaweedfs

# 启动 master
docker run -d \
-p 9333:9333 \
-p 19333:19333 \
-v /home/mining/report-cloud/docker/seaweedfs/master/data:/data \
--name seaweedfs-master \
chrislusf/seaweedfs:1.53 \
master -ip=master # 启动 volume
docker run -d \
-p 8080:8080 \
-p 18080:18080 \
-v /home/mining/report-cloud/docker/seaweedfs/volume01/data:/data \
--name seaweedfs-volume \
--link seaweedfs-master:master \
chrislusf/seaweedfs:1.53 \
volume -max=5 -mserver="master:9333" -port=8080

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

简单使用:

# 申请空间
curl http://localhost:9333/dir/assign
#
{"count":1,"fid":"4,017f52110b","url":"127.0.0.1:8080","publicUrl":"localhost:80
80"}
# 推送文件,4,017f52110b表示第4个volume,017f52110b表示文件的唯一标识
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

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

Java代码

maven依赖

<!-- oss 存储的依赖 -->
<!-- seaweedfs 依赖 -->
<dependency>
<groupId>org.lokra.seaweedfs</groupId>
<artifactId>seaweedfs-client</artifactId>
<version>0.7.3.RELEASE</version>
</dependency> <!-- minio 依赖 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>3.0.10</version>
</dependency>

代码

配置类

FileTag 枚举类

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

/**
* 文件上传的tag
*/
public enum FileTag {
TYPE_LOCAL,
TYPE_MINIO ,
TYPE_SEAWEEDFS;
}

FileUploadConfigLocal

本地存储配置类

public class FileUploadConfigLocal {
private String parentPath;
// 省略 get set
}

FileUploadConfigSeaweedfs

seaweedfs存储配置类

public class FileUploadConfigSeaweedfs {
private String host;
private int port = 9333;
private String publicUrl;
private int connectTimeout = 60; // 60 s
// 省略 get set
}

FileUploadConfigMinio

minio存储配置类

public class FileUploadConfigMinio {
private String domain; // url 前缀
private String accesKey;
private String secretKey;
private String bucket; // 必须事先创建好
// 省略 get set
}

FileUploadConfig

spring application.yaml 配置类

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties( prefix = "oss-config")
public class FileUploadConfig {
FileTag tag;
FileUploadConfigLocal local;
FileUploadConfigSeaweedfs seaweedfs;
FileUploadConfigMinio minio;
// 省略 get set
}

配置文件

application.yaml

# 对象存储配置
oss-config:
tag: TYPE_LOCAL # 使用哪种存储介质
local:
parent-path: D:\dev\2019-06-19\upload
minio:
domain: http://localhost:19000
bucket: report
acces-key: qweasdzxc
secret-key: 1234567890
seaweedfs:
host: localhost
port: 9333
publicUrl: http://localhost:8080
connectTimeout: 3000 # 5min

FileUploadInfoVO文件上传类

public class FileUploadInfoVO {

    private String fileName; // 文件名
private String suffix; // 文件后缀
private String contentType; // 文件类型
private Long size; // 文件大小
private String fid; // 文件唯一ID,同时也是保存在服务器上的文件名
private boolean delete; // 是否删除,默认false
private String description;
private String url; // 完整的url
private String tag; // 标签,比如
private String uploadTime;
private String deleteTime;
// 省略 get set
}

业务逻辑类

FileStorageService 文件存储接口

/**
* 文件存储的接口
*/
public interface FileStorageService {
FileUploadInfoVO upload(InputStream in, FileUploadInfoVO fileUploadInfoVO) throws Exception ;
FileUploadInfoVO upload(byte[] bytes, FileUploadInfoVO fileUploadInfoVO) throws Exception ;
FileUploadInfoVO delete(FileUploadInfoVO fileUploadInfoVO) throws Exception ;
}

本地存储实现

@Service("FileStorageServiceLocal")
public class FileStorageServiceLocal implements FileStorageService { @Autowired
FileUploadConfig fileUploadConfig; @PostConstruct
public void init() {
FileUtils.checkAndCreateDir(fileUploadConfig.getLocal().getParentPath());
} @Override
public FileUploadInfoVO upload(InputStream in, FileUploadInfoVO fileUploadInfoVO) throws Exception {
String filePath = fileUploadConfig.getLocal().getParentPath() + File.separator + fileUploadInfoVO.getFid();
FileUtils.copyFileFromInputStream(in, filePath);
fileUploadInfoVO.setUrl(filePath+"."+fileUploadInfoVO.getSuffix());
return fileUploadInfoVO;
} @Override
public FileUploadInfoVO upload(byte[] bytes, FileUploadInfoVO fileUploadInfoVO) throws Exception {
String filePath = fileUploadConfig.getLocal().getParentPath() + File.separator + fileUploadInfoVO.getFid();
FileUtils.copyFileFromBytes(bytes, filePath);
fileUploadInfoVO.setUrl(filePath);
return fileUploadInfoVO;
} @Override
public FileUploadInfoVO delete(FileUploadInfoVO fileUploadInfoVO) throws Exception {
File file = new File(fileUploadInfoVO.getUrl());
if(file.exists()) {
file.delete();
}
return fileUploadInfoVO;
}
}

Seaweedfs存储实现

@Service("FileStorageServiceSeaweedfs")
public class FileStorageServiceSeaweedfs implements FileStorageService { @Autowired
FileUploadConfig fileUploadConfig; FileTemplate fileTemplate; @PostConstruct
public void init() {
FileUploadConfigSeaweedfs seaweedfs = fileUploadConfig.getSeaweedfs();
FileSource fileSource = new FileSource();
fileSource.setHost(seaweedfs.getHost());
fileSource.setPort(seaweedfs.getPort());
fileSource.setConnectionTimeout(seaweedfs.getConnectTimeout());//5min
try {
fileSource.startup();
} catch (IOException e) {
throw new RuntimeException("创建seaweedfs连接失败,原因是:" + e.getMessage());
}
fileTemplate = new FileTemplate(fileSource.getConnection(), seaweedfs.getPublicUrl());
} @Override
public FileUploadInfoVO upload(InputStream in, FileUploadInfoVO fileUploadInfoVO) throws Exception {
FileHandleStatus fileHandleStatus = fileTemplate.saveFileByStream(fileUploadInfoVO.getFileName(), in, ContentType.create(fileUploadInfoVO.getContentType(), "utf-8"));
fileUploadInfoVO.setFid(fileHandleStatus.getFileId());
fileUploadInfoVO.setUrl(String.format("%s/%s", fileUploadConfig.getSeaweedfs().getPublicUrl(), fileHandleStatus.getFileId()));
return fileUploadInfoVO;
} @Override
public FileUploadInfoVO upload(byte[] bytes, FileUploadInfoVO fileUploadInfoVO) throws Exception {
return upload(new ByteArrayInputStream(bytes), fileUploadInfoVO);
} @Override
public FileUploadInfoVO delete(FileUploadInfoVO fileUploadInfoVO) throws Exception {
fileTemplate.deleteFile(fileUploadInfoVO.getFid());
return fileUploadInfoVO;
}
}

Minio存储实现

@Service("FileStorageServiceMinio")
public class FileStorageServiceMinio implements FileStorageService { @Autowired
FileUploadConfig fileUploadConfig; @Override
public FileUploadInfoVO upload(InputStream in, FileUploadInfoVO fileUploadInfoVO) throws Exception {
FileUploadConfigMinio minio = fileUploadConfig.getMinio();
String domain = minio.getDomain();
String bucket = minio.getBucket();
String fileName = fileUploadInfoVO.getFileName();
MinioClient minioClient = new MinioClient(domain, minio.getAccesKey(), minio.getSecretKey());
minioClient.putObject("report", fileName, in, fileUploadInfoVO.getSize(), fileUploadInfoVO.getContentType());
fileUploadInfoVO.setUrl(String.format("%s/%s/%s", domain, bucket, fileName));
return fileUploadInfoVO;
} @Override
public FileUploadInfoVO upload(byte[] bytes, FileUploadInfoVO fileUploadInfoVO) throws Exception {
return upload(new ByteArrayInputStream(bytes), fileUploadInfoVO);
} @Override
public FileUploadInfoVO delete(FileUploadInfoVO fileUploadInfoVO) throws Exception {
FileUploadConfigMinio minio = fileUploadConfig.getMinio();
MinioClient minioClient = new MinioClient(minio.getDomain(), minio.getAccesKey(), minio.getSecretKey());
minioClient.removeObject(minio.getBucket(), fileUploadInfoVO.getFileName());
return fileUploadInfoVO;
}
}

存储工厂类实现

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

@Service
public class FileStorageFactory { Map<FileTag, FileStorageService> fileStorageServiceMap; @Qualifier("FileStorageServiceLocal")
@Autowired
FileStorageService fileStorageServiceLocal; @Qualifier("FileStorageServiceSeaweedfs")
@Autowired
FileStorageService fileStorageServiceSeaweedfs; @Qualifier("FileStorageServiceMinio")
@Autowired
FileStorageService fileStorageServiceMinio; @PostConstruct
public void init() {
fileStorageServiceMap = new HashMap<>();
fileStorageServiceMap.put(FileTag.TYPE_LOCAL, fileStorageServiceLocal);
fileStorageServiceMap.put(FileTag.TYPE_SEAWEEDFS, fileStorageServiceSeaweedfs);
fileStorageServiceMap.put(FileTag.TYPE_MINIO, fileStorageServiceMinio);
} public FileStorageService get(FileTag type) {
FileStorageService fileStorageService = fileStorageServiceMap.get(type);
return fileStorageService == null ? fileStorageServiceMap.get(FileTag.TYPE_LOCAL) : fileStorageService;
}
}

业务中实现

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

eg:

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

这样,配置文件中可以使用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. 我的.vimrc配置

    termux平台下,通过pkg update && pkg upgrade && pkg install vim来获得vim.可是,当我配置.vimrc时发现如果我每在 ...

  2. zsy后台管理系统-架构设计

    Zsy框架总体架构设计 1.Mysql数据库,存储所有表的数据. 2.Zsy-基础项目(Zsy-Model,Zsy-Dao,Zsy-Service,Zsy-Web),基于SSM框架.项目功能包含基本的 ...

  3. Java线程的几种可用状态

    1. 新建( new ):新创建了一个线程对象. 2. 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 start()方法.该状态的线程位于可运行线程 ...

  4. 使用pandas库实现csv行和列的获取

    1.读取csv import pandas as pd df = pd.read_csv('路径/py.csv') 2.取行号 index_num = df.index 举个例子: import pa ...

  5. 浙工大新生赛莫队处理+区间DP+KMP+分析题

    题目描述 读入一个长度为n的整数数列a1,a2,…,an,以及一个整数K. q组询问. 每组询问包含一个二元组(l, r), 其中1≤l≤r≤ n, 求所有满足以下条件的二元组(l2, r2)的数目: ...

  6. 玩转java反射

    玩玩JAVA反射 什么是反射 Java反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法:对于任何一个对象,都能够调用它的任何一个方法和属性:这样动态获取新的以及动态调用对象的方法 ...

  7. python 格式化输出(% VS format)

    提到Python中的格式化输出方法,一般来说有以下两种方式: 1)% 格式说明由%和格式字符组成,如%f,%s,%d,它的作用是将数据按照指定的格式输出.格式说明是由“%”字符开始的. #1.输出字符 ...

  8. Pyqt5_实例1

    #coding=utf-8 ''' Created on 2018年11月2日 @author: yanerfree ''' import sys from PyQt5.QtWidgets impor ...

  9. (一) Vue在创建的时候 入口文件 及相关的路由配置(及子路由配置)

    1. 首先明确一点  在书写之前尽量保持相关的文件知道含义 比如 components 啥的 知道是要放什么东西 在这里介绍一下   由于 vue 不是系统学习 所以很多的创建方式可能不一样  就是有 ...

  10. vue 下拉列表动画

    点击可以收起,这里注意先给需要收起展开的的容器设置高度,通过样式v-enter和v-leave-to设置结束和开始前的就可以了