文件上传是常见需求,一般我们不会直接把文件保存在服务器的某个目录下,因为服务器的存储容量是有限的,这样不好扩展。
我们会用 OSS (Object Storage Service)对象存储服务来存文件,它是支持分布式扩展的,不用担心存储容量问题,而且也好管理。
比如阿里云的 OSS 服务。
但是有一些业务场景下,数据需要保密,要求私有部署,也就是要在自己的机房里部署一套 OSS 服务。
这时候怎么办呢?
这种需求一般我们会用 minio 来做。
它可以实现和阿里云 OSS 一样的功能。
首先,我们用一下阿里云的 OSS 服务。
OSS 里的文件是放在一个个 Bucekt(桶)里的:
我们创建个 Bucket:
然后进入文件列表,就可以上传文件了:
因为创建的 Bucket 设置了公共读,所以可以直接访问:
此外,阿里云 OSS 还可以通过 SDK 来上传文件。
创建个项目:
mkdir minio-test
cd minio-test
npm init -y
进入项目,安装 ali-oss:
npm install ali-oss
创建 index.js
const OSS = require('ali-oss')
const client = new OSS({
region: 'oss-cn-beijing',
bucket: 'guang-666',
accessKeyId: '',
accessKeySecret: '',
});
async function put () {
try {
const result = await client.put('smile.png', './smile.png');
console.log(result);
} catch (e) {
console.log(e);
}
}
put();
填入 region、bucket 和 accessKeyId、accessKeySecret
这里的 region 可以从概览里看到:
acessKey 是在这里看:
具体创建 accessKey 的流程看上篇文章
然后跑一下:
上传成功之后就可以通过 OSS 服务访问这个图片了:
也可以通过 sdk 下载图片:
执行后可以看到,图片被下载下来了:
这就是阿里云 OSS 的用法。
那我们用 minio 自己搭呢?
首先,我们需要安装 docker 桌面端:
打开后可以看到本地的所有镜像和容器:
搜索下 minio(这步需要科学上网):
填入一些信息:
name 是容器名。
port 是映射本地 9000 和 9001 端口到容器内的端口。
volume 是挂载本地目录到容器内的目录
这里挂载了一个本地一个目录到容器内的数据目录 /bitnami/minio/data,这样容器里的各种数据都保存在本地了。
还要指定两个环境变量,MINIO_ROOT_USER 和 MINIO_ROOT_PASSWORD,是用来登录的。
点击 run,跑起来之后可以看到数据目录被标记为 mounted,端口也映射成功了:
访问下 http://localhost:9001
输入刚才环境变量填的用户名密码:
进入管理界面:
这个 bucket 就是管理桶的地方,而 object browser 就是管理文件列表的地方。
和阿里云 OSS 用法一样。
我们创建个 bucket:
然后在这个 bucket 下上传一个文件:
点击 share 就可以看到这个文件的 url:
现在倒是能在浏览器访问,只不过需要带后面的一长串东西:
不带的话会提示拒绝访问:
image.png
因为现在文件访问权限不是公开的。
我们设置下:
添加一个 / 的匿名的访问规则。
然后就可以直接访问了:
是不是感觉用起来和阿里云的 OSS 差不多?
我们再来试试 sdk 的方式:
npm install minio
安装 minio 包。
然后创建 index2.js
var Minio = require('minio')
var minioClient = new Minio.Client({
endPoint: 'localhost',
port: 9000,
useSSL: false,
accessKey: '',
secretKey: '',
})
function put() {
minioClient.fPutObject('aaa', 'hello.png', './smile.png', function (err, etag) {
if (err) return console.log(err)
console.log('上传成功');
});
}
put();
创建用到的 accessKey:
跑一下:
可以看到,文件上传成功了:
同样,也可以下载文件:
const fs = require('fs');
function get() {
minioClient.getObject('aaa', 'hello.png', (err, stream) => {
if (err) return console.log(err)
stream.pipe(fs.createWriteStream('./xxx.png'));
});
}
get();
用起来和阿里云 OSS 几乎一毛一样。
更多的 api 用法可以看 minio 文档。
最后,还记得我们跑 docker 容器的时候指定了挂载目录么:
这样,数据就会保存在本地的那个目录下:
那为什么 OSS 服务都这么相似呢?
因为它们都是遵循 AWS 的 Simple Storage Service(S3)规范的,简称 S3 规范。
所以不管哪家的 OSS,用起来都是差不多的。
案例代码上传了 github:https://github.com/QuarkGluonPlasma/nestjs-course-code/tree/main/minio-test
总结
文件上传一般我们都是用 OSS 服务来存储,比如阿里云的 OSS。
但是 OSS 是收费的,而且有些敏感数据不能传到云上,需要私有部署,这种就可以自己搭一个 OSS 服务。
我们用 docker 跑了一个 minio 的容器,然后分别在管理界面和用 npm 包的方式做了文件上传和下载。
用法和阿里云 OSS 差不多,因为他们都是亚马逊 S3 规范的实现。
你公司内部有没有自己用 minio 搭 OSS 服务呢?