MinIO
TIP
MinIO
是一个对象存储服务。它非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件等,而一个对象文件可以是任意大小,从几kb到最大5T不等。而且它既支持服务端部署,也支持前端直连(通过SDK),本文主要介绍前端直连MinIO服务的详细过程。
MinIO相关文档
前端使用
- 安装
bash
npm i minio -S
- 文件操作通用方法
src/utils/minio.js
查看代码
js
const Minio = require('minio')
const stream = require('stream')
/**
* @description 生成唯一文件名(规则:文件名+uid)
* @param {string} name 初始文件名,带文件后缀
* @param {string} uid 文件唯一标识
*/
function generateFileName(name, uid) {
const spotIndex = name.lastIndexOf('.')
const fileName = name.substring(0, spotIndex)
const fileSuffix = name.substring(spotIndex)
return `${fileName}_${uid}${fileSuffix}`
}
/**
* @description 建立MinIO连接
* @param {string} bucketName 存储桶名称
*/
export function createMinioClient(bucketName) {
return new Promise((resolve, reject) => {
/* 此服务是MinIO官方提供的测试服务,使用时可根据实际环境更改相关信息 */
const minioClient = new Minio.Client({
endPoint: 'play.min.io',
port: 9000,
useSSL: true,
accessKey: 'Q3AM3UQ867SPQQA43P2F',
secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG'
})
minioClient.bucketExists(bucketName).then(res => {
if (!res) {
minioClient.makeBucket(bucketName, 'us-east-1', function(error) {
if (error) {
reject(error)
}
resolve(minioClient)
})
}
resolve(minioClient)
}).catch(err => {
reject(err)
})
})
}
/**
* @description 上传文件
* @param {Object} minioClient minio实例
* @param {Object} file 文件
* @param {string} bucketName 存储桶
*/
export function minioUpload(minioClient, file, bucketName) {
return new Promise((resolve, reject) => {
const fileName = generateFileName(file.name, file.uid)
const blob = new Blob([file], { type: file.type })
const reader = new FileReader()
reader.readAsArrayBuffer(blob)
reader.onload = function(e) {
const buffer = e.target.result
const bufferStream = new stream.PassThrough()
bufferStream.end(new Buffer(buffer))
minioClient.putObject(bucketName, fileName, bufferStream, file.size, function(err, etag) {
if (err) {
reject(err)
}
resolve(etag)
})
}
})
}
/**
* @description 下载文件
* @param {Object} minioClient minio实例
* @param {string} bucketName 存储桶
* @param {Object} file 文件
* @param {string} fileUID 文件uid
*/
export function minioDownload(minioClient, bucketName, file, fileUID) {
return new Promise((resolve, reject) => {
const fileName = generateFileName(file.name, fileUID)
minioClient.presignedGetObject(bucketName, fileName, 24 * 60 * 60, function(error, url) {
if (error) {
return reject(error)
}
resolve(url)
})
})
}
/**
* @description 删除文件
* @param {Object} minioClient minio实例
* @param {string} bucketName 存储桶
* @param {Object} file 文件
* @param {string} fileUID 文件uid
*/
export function minioRemove(minioClient, bucketName, file, fileUID) {
return new Promise((resolve, reject) => {
const fileName = generateFileName(file.name, fileUID)
minioClient.removeObject(bucketName, fileName, function(err) {
if (err) {
reject(err)
}
resolve(true)
})
})
}
- Vue中使用 (此处使用Element中的上传组件)
vue
<template>
<div>
<el-upload
action=""
multiple
:auto-upload="false"
:show-file-list="true"
:file-list="fileList"
:on-change="(f, list) => handleFileChange(f, list)"
:on-preview="handleFilePreview"
:on-remove="(f, list) => handleFileRemove(f, list)"
>
<el-button type="primary" icon="el-icon-upload">选择附件</el-button>
</el-upload>
</div>
</template>
<script>
import { createMinioClient, minioUpload, minioDownload, minioRemove } from '@/utils/minio'
export default {
data() {
return {
loading: false,
minioClient: null // MinIO实例
}
},
created() {
// 创建MinIO实例
this.loading = true
createMinioClient().then(res => {
this.minioClient = res
}).finally(() => {
this.loading = false
})
},
methods: {
handleFileChange(file, fileList) {
if (!this.minioClient) return
minioUpload(this.minioClient, file.raw, 'xx').then(res => {
// success & do something
})
},
handleFilePreview(file) {
minioDownload(this.minioClient, 'xx', file, file.uid).then(url => {
// do something
// 下载文件
window.open(url, '_self')
})
},
handleFileRemove(file) {
minioRemove(this.minioClient, 'xx', file, file.uid).then(res => {
// do something
})
}
}
}
</script>