文件上传是常见需求,一般我们不会直接把文件保存在服务器的某个目录下,因为服务器的存储容量是有限的,这样不好扩展。
我们会用 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 那节
然后跑一下:
上传成功之后就可以通过 OSS 服务访问这个图片了:
也可以通过 sdk 下载图片:
执行后可以看到,图片被下载下来了:
这就是阿里云 OSS 的用法。
那我们用 minio 自己搭呢?
首先,我们需要安装 docker 桌面端:
打开后可以看到本地的所有镜像和容器:
搜索下 minio(这步需要科学上网):
填入一些信息:
name 是容器名。
port 是映射本地 9000 和 9001 端口到容器内的端口。
volume 是挂载本地目录到容器内的目录
这里挂载了一个本地一个目录到容器内的数据目录 /bitnami/minio/data,这样容器里的各种数据都保存在本地了。
还要指定两个环境变量,MINIO_ROOT_USER 和 MINIO_ROOT_PASSWORD,是用来登录的。
点击 run,跑起来之后可以看到数据目录被标记为 mounted,端口也映射成功了:
输入刚才环境变量填的用户名密码:
进入管理界面:
这个 bucket 就是管理桶的地方,而 object browser 就是管理文件列表的地方。
和阿里云 OSS 用法一样。
我们创建个 bucket:
然后在这个 bucket 下上传一个文件:
点击 share 就可以看到这个文件的 url:
现在倒是能在浏览器访问,只不过需要带后面的一长串东西:
不带的话会提示拒绝访问:
因为现在文件访问权限不是公开的。
我们设置下:
添加一个 / 的匿名的访问规则。
然后就可以直接访问了:
是不是感觉用起来和阿里云的 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,用起来都是差不多的。
案例代码上传了小册仓库。
总结
文件上传一般我们都是用 OSS 服务来存储,比如阿里云的 OSS。
但是 OSS 是收费的,而且有些敏感数据不能传到云上,需要私有部署,这种就可以自己搭一个 OSS 服务。
我们用 docker 跑了一个 minio 的容器,然后分别在管理界面和用 npm 包的方式做了文件上传和下载。
用法和阿里云 OSS 差不多,因为他们都是亚马逊 S3 规范的实现。
你公司内部有没有自己用 minio 搭 OSS 服务呢?