若是想搭建一个优雅、简单、功能完备的静态资源服务,那就用MinIO吧。css
开发 Web 项目过程当中,常常须要处理静态资源(如图片、视频、音频,js库 ,css 库等),通常来讲,若项目中须要用到这些资源文件,咱们经常使用的有如下几种方法:html
对于本地存储,缺点就很明显,资源与代码文件混合一块儿,没有必要,并且不方便扩展。对于本地内部部署的应用,显然是本身搭建静态资源服务比较稳妥。对于使用代理服务和第三方工具,相比起来,代理服务仅作映射,虽然可用,但功能单一,仅作映射,没有其它管理功能,也不方便扩展。使用第三方文件或对象存储工具,能够对文件进行管理、也能考虑高扩展,高性能、高可用等因素,所以是很好的选择,其中,MinIO 就是这样一款好用的对象存储工具,简单,快捷并且功能完备。java
本文则是经过对 MinIO 的安装、配置与使用,构建静态资源服务,从而把图片、视频、音频,第三方 js 库等资源独立部署,访问;还会对 MinIO 提供的 Java API 进行使用简单介绍,以便于进一步开发。linux
按 MinIO 官方介绍,MinIO 是高性能的对象存储(块存储、文件存储和对象存储的区别,可参考架构师都知道的分布式对象存储解决方案),兼容 Amazon S3 接口,充分考虑开发人员的需求和体验;支持分布式存储,具有高扩展性、高可用性;部署简单但功能丰富。官方的文档也很详细。它有多种不一样的部署模式(单机部署,分布式部署)。为何说 MinIO 简单易用,缘由就在于它的启动、运行和配置都很简单。能够经过 docker 方式进行安装运行,也能够下载二进制文件,而后使用脚本运行。nginx
本文以最简单的方式进行讲解,在 linux 机器中,单机部署,运行二进制文件。git
MinIO 开发文档中,下载地址以下:github
https://dl.min.io/server/minio/release/linux-amd64/minio
https://dl.min.io/server/minio/release/windows-amd64/minio.exe
本文在 linux 中运行。spring
把下载的 minio 文件存放到某个目录做为运行目录(如 /opt/minio),新建一个目录(如/opt/minio-data)做为 minio 数据存储位置,便可启动,以下脚本:docker
cd /opt/minio
chmod +x minio
./minio server /opt/minio-data
复制代码
启动后会输出访问地址 endpoint 和对应的 access_key 和 secret_key,使用浏览器访问 endpoint 地址,若能够访问,则表示 minio 已经安装成功。不过这样启动会有几个缺点:shell
ctrl+c
就会结束进程,服务就中止针对这些问题,建议使用下面的方式进行启动运行。
使用 nohup
在后台运行程序,同时指定密码参数,访问地址参数和日志输出,以下所示。
MINIO_ACCESS_KEY=minio MINIO_SECRET_KEY=minio123 nohup /opt/minio/minio server --address "${MINIO_HOST}:${MINIO_PORT}" /opt/minio-data > /opt/minio/minio.log 2>&1 &
复制代码
MINIO_ACCESS_KEY
及MINIO_SECRET_KEY
是访问密码
${MINIO_HOST}:${MINIO_PORT}
分别是访问的 host 和端口,请按实际状况修改。
这样,经过浏览器访问地址 ${MINIO_HOST}:${MINIO_PORT}
,使用指定的 MINIO_ACCESS_KEY
及 MINIO_SECRET_KEY
登陆便可。
在浏览器中登陆到 MinIO 存储系统,点击右下角建立 bucket 来存储对象,分别建立对应的 bucket 以存放静态资源:image,video,audio。这样,就能够按资源类型在对应的 bucket 中进行文件上传了,上传后能够把文件分享,其它地方能够经过分享的 url 获取资源,以下图所示。
MinIO 默认的策略是分享地址的有效时间最可能是7天,要突破这种限制,能够在 bucket 中进行策略设置。点击对应的 bucket ,edit policy
添加策略 *.*
,Read Only
,以下:
如此就放开了访问,没有时间限制,同时只须要按http://${MINIO_HOST}:${MINIO_PORT}/${bucketName}/${fileName}
则可直接访问资源(不须要进行分享操做)。
关于 MinIO 目录的误区
- 其实对于对象存储来讲,其实不区分文件仍是目录,全部文件和目录都是对象,即 image/temp/xxx.jpg 和 image/temp/ 都是对象。它跟操做系统的文件系统的树状结构有本质区别。
- 上传文件时,objectName 能够是
/temp/xxx.jpg
,能够认为系统自动建立了temp目录。- MinIO 不会提供像删除目录,同时删除此目录下全部文件的操做(即
rm -rf image/temp
),所以要想把目录 image/temp 删除,则须要先把以 image/temp 为前缀的全部文件删除。- 查询多个文件时,可使用前缀匹配方式获取,见 API 文档
listObjects(bucketName, prefix, recursive)
经过上面的设置与运行,MinIO 做为静态资源服务器已经完成,能够写个 html 来引用 MinIO 中的静态资源。以下是测试的 html 里面的图片、视频、音频均使用 MinIO 的资源地址。
<div class="img-list">
<img src="http://${MINIO_HOST}:${MINIO_PORT}/image/test.jpg" alt="图片">
</div>
<div class="audio-list">
<audio src="http://${MINIO_HOST}:${MINIO_PORT}/audio/test.mp3" controls="controls"></audio>
</div>
<div class="video-list">
<video src="http://${MINIO_HOST}:${MINIO_PORT}/video/test.mp4" controls="controls"></video>
</div>
复制代码
可发现资源是能够正常加载访问的。
MinIO 对开发者是很是友好的,提供了各类语言的 API 操做接口,具体能够参考 MinIO开发文档。下面以 Java 为例作一下测试。
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>6.0.13</version>
</dependency>
复制代码
创建 MinIO 的操做客户端 minioClient = new MinioClient(endpoint, accessKey, secretKey);
,参数中endpoint
是 MinIO 的访问地址,后面两对应启动时设置的密码。
/** * 上传文件 * @param minioClient 操做客户端 * @param bucketName 上传的bucket名称 * @param objectName 上传后存储在bucket中的文件名 * @param filePath 上传的本地文件路径 */
public void uploadFile(MinioClient minioClient, String bucketName, String objectName, String filePath) throws XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, IOException {
try {
// 若不存在bucket,则新建
boolean isExist = minioClient.bucketExists(bucketName);
if (!isExist) {
minioClient.makeBucket(bucketName);
}
// 使用 putObject 上传文件
minioClient.putObject(bucketName, objectName, filePath, null, null, null, null);
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
}
}
复制代码
/** * 下载文件 * * @param minioClient 操做客户端 * @param bucketName 上传的bucket名称 * @param objectName 上传后存储在bucket中的文件名 * @param downloadPath 下载文件保存路径 */
public void downloadFile(MinioClient minioClient, String bucketName, String objectName, String downloadPath) throws XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, IOException {
File file = new File(downloadPath);
try (OutputStream out = new FileOutputStream(file)) {
InputStream inputStream = minioClient.getObject(bucketName, objectName);
byte[] tempbytes = new byte[1024];
int byteread = 0;
while ((byteread = inputStream.read(tempbytes)) != -1) {
out.write(tempbytes, 0, byteread);
}
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
}
}
复制代码
删除文件简单,使用removeObject
便可。
minioClient.removeObject(bucketName, objectName);
复制代码
/** * 罗列文件 * @param minioClient * @param bucketName */
public void listFile(MinioClient minioClient, String bucketName) throws XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, IOException {
try {
Iterable<Result<Item>> results = minioClient.listObjects(bucketName);
Iterator<Result<Item>> iterator = results.iterator();
while (iterator.hasNext()) {
Item item = iterator.next().get();
System.out.println(item.objectName() + ", " + item.objectSize() + "B");
}
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
}
}
复制代码
因为有对静态资源进行独立访问的需求,进行动静分离,经过使用 MinIO ,能够快速简单的实现静态资源服务器,以供访问。本文经过对 MinIO 的下载、部署、启动、运行、配置等描述,并以 html 引用静态资源文件为例,讲解 MinIO 的使用,并提供 Java API 的简单使用。但愿对你们有帮助。
本文中使用了 nohup 对 MinIO 进行启动,但命令太长,通常咱们都会写成脚本,以实现启动、关闭及状态查询,所以,我把脚本写成完整的 sh 文件,以供你们使用。另外,MinIO Java API 的测试,本示例使用的是 Spring Boot 项目,以单元测试的方式进行。
sh脚本文件及 Spring Boot 工程一块儿放在个人 minio github 示例 中(脚本minio-serviced.sh
在 scripts 目录下),有须要的可下载参考。
脚本使用方法:
- 根据实际状况修改sh脚本中的参数
- 修改执行权限:chmod +x minio-serviced.sh
- 按参数启动/关闭/重启/运行状态:./minio-serviced.sh start/stop/restart/status
https://min.io/
https://docs.min.io/
https://mp.weixin.qq.com/s/MzA4ODg0NDkzOA==&mid=2247487119&idx=1&sn=6e09abb32392e015911be3a1d7f066e5&source=41
https://juejin.im/post/5cdc16e251882568651553f9
https://tonybai.com/2020/03/16/build-high-performance-object-storage-with-minio-part1-prototype
个人公众号(搜索Mason技术记录
),获取更多技术记录: