Minio 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
Minio是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
Minio不仅提供了服务器、Web访问、客户端,还提供了Docker安装,各种语言的SDK、实例、实战秘籍等等,支持分布式部署,[官方文档](https://docs.minio.io)一应俱全。
Minio各个系统的安装均非常简单,这里仅介绍MacOS系统的安装,其他系统[官方文档](https://docs.minio.io)均有详细介绍,这里不再过多赘述。
Install minio packages using Homebrew
brew install minio/stable/minio
minio server /data
NOTE: If you previously installed minio using
brew install minio
then it is recommended that you reinstall minio fromminio/stable/minio
official repo instead.
brew uninstall minio
brew install minio/stable/minio
Platform | Architecture | URL |
---|---|---|
Apple macOS | 64-bit Intel | https://dl.minio.io/server/minio/release/darwin-amd64/minio |
chmod 755 minio
./minio server /data
安装后运行启动命令,启动成功后使用浏览器访问http://127.0.0.1:9000,如果可以访问,则表示Minio已安装成功。
输入运行时生成的两个Key便可以成功访问:
Minio server在默认情况下会将所有配置信息存到 `${HOME}/.minio/config.json` 文件中。 以下部分提供每个字段的详细说明以及如何自定义它们。一个完整的 `config.json` 在 [这里](https://raw.githubusercontent.com/minio/minio/master/docs/config/config.sample.json)
默认的配置目录是 `${HOME}/.minio`,你可以使用`--config-dir`命令行选项重写之。 Minio server在首次启动时会生成一个新的`config.json`,里面带有自动生成的访问凭据。
minio server --config-dir /etc/minio /data
详见官方文档,[Minio Server Config Guide](https://docs.minio.io/docs/minio-server-configuration-guide.html)
Minio客户端,Minio Client (mc)为ls,cat,cp,mirror,diff,find等UNIX命令提供了一种替代方案。它支持文件系统和兼容Amazon S3的云存储服务(AWS Signature v2和v4)。详见官方文档,[Minio Client Quickstart Guide](https://docs.minio.io/docs/minio-client-quickstart-guide.html)
Minio官方文档为各种语言提供了SDK及详细的接口说明。
最低要求:
Maven:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>3.0.10</version>
</dependency>
Gradle:
dependencies {
compile 'io.minio:minio:3.0.10'
}
Minio是根据请求头来判断文件类型的,操作时如果有预览需求,一定要注意请求头的设置,比如:
/**
* 以流的形式上传对象
*
* @param bucketName 存储桶名称
* @param objectName 对象名称
* @param stream 流
* @return 是否成功
*/
public Boolean putObject(String bucketName, String objectName, InputStream stream) {
try {
ifBucketExists(bucketName);
// 创建对象
minioClient.putObject(bucketName, objectName, stream, stream.available());
stream.close();
logger.info("object is uploaded successfully");
return true;
} catch (MinioException e) {
logger.error("存储服务器异常。");
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
logger.error("找不到相应的签名算法。");
e.printStackTrace();
} catch (XmlPullParserException e) {
logger.error("XmlPullParserException");
e.printStackTrace();
} catch (InvalidKeyException e) {
logger.error("不合法的access key或者secret key。");
e.printStackTrace();
} catch (IOException e) {
logger.error("连接异常。");
e.printStackTrace();
}
return false;
}
上面实例中,采用此方法上传的文件,不论图片还是文本,在存储桶中展示均为灰色的文件,这样会导致外联会直接下载文件,从而起不到预览的效果,如下图标红所示:
这是因为Minio的SDK中,默认的请求头为application/octet-stream,源码中也证明了这一点:
if (body != null) {
requestBody = new RequestBody() {
public MediaType contentType() {
MediaType mediaType = null;
if (contentType != null) {
mediaType = MediaType.parse(contentType);
}
if (mediaType == null) {
mediaType = MediaType.parse("application/octet-stream");
}
return mediaType;
}
.
.
.
}
将方法改为 如下调用:
try {
minioClient.putObject(bucketName, objectName, stream, stream.available(), "image/jpg");
stream.close();
logger.info("object is uploaded successfully");
return true;
}
这样上传jpg格式的图片,分享的连接就可以预览了。
Minio官方文档有配置nginx代理的说明,但是如果应用到业务当中还是会踩一下坑,在实际应用中,我希望通过配置应用名称的方法达到Java 应用可以连接、分享连接可以下载文件、URL可以直接登录的目的,然后加入如下配置:
location /files {
proxy_buffering off; //重要!
proxy_set_header Host $http_host;
proxy_pass http://localhost:9000;
}
# 或者
location /minio {
proxy_buffering off; //重要!
proxy_set_header Host $http_host;
proxy_pass http://localhost:9000/minio;
}
但是这两种配置均不能达到我所希望的效果,第一种直接重定向失败、第二种可以实现网页登录,但是无法实现Java程序连接,连接时报错:
io.minio.errors.InvalidEndpointException: no path allowed in endpoint
意思是路径不被允许,定位到其源码:
if (url != null) {
if (!"/".equals(url.encodedPath())) {
throw new InvalidEndpointException(endpoint, "no path allowed in endpoint");
} else {
String amzHost = url.host();
if (amzHost.endsWith(".amazonaws.com") && !amzHost.equals("s3.amazonaws.com")) {
throw new InvalidEndpointException(endpoint, "for Amazon S3, host should be 's3.amazonaws.com' in endpoint");
} else {
Builder urlBuilder = url.newBuilder();
Scheme scheme = Scheme.HTTP;
if (secure) {
scheme = Scheme.HTTPS;
}
urlBuilder.scheme(scheme.toString());
if (port > 0) {
urlBuilder.port(port);
}
this.baseUrl = urlBuilder.build();
this.accessKey = accessKey;
this.secretKey = secretKey;
this.region = region;
}
}
}
其中:
if (!"/".equals(url.encodedPath())) {
throw new InvalidEndpointException(endpoint, "no path allowed in endpoint");
}
猜测Minio的endpoint仅支持到root,也就是/目录下,所以在nginx配置中新加了一个server:
server {
listen 80; #或者443
server_name file.example.com;
location / {
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_pass http://localhost:9000;
}
}
也就是Minio官方文档上给出的配置。
这样配置对强迫症不太友好,但是为了实现业务职能把Minio的代理单独一个server,配置唯一的二级域名来代理。
如果你在上传时遇到了EOFException异常,无论是客户端还是服务端,回去检查你的nginx配置,记得一定在映射下加上如下代码:
proxy_buffering off;
minio单机版到这里,就告一段落了,由于项目紧急,未能对Minio集群进行研究,待今后有机会再将此文档完善。