前端上传文件到minio,并从minio下载下来此文件。
api: https://docs.min.io/docs/javascript-client-api-reference.html
我在react中使用的,在index.js中引入下方minio.js
/*
services: minio配置信息
{
endPoint: 'hostname',
port: 9000,
useSSL: true, // true:https false:http
accessKey: 'Q3AM3UQ867SPQQA43P2F',
secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG'
}
*/
// 上传文件
onChange =(info) => {
const { clientVersion: { services } } = this.props;
const { fileList } = this.state;
// 删除文件
if (info.file.status === 'removed') {
this.setState({
filePath:'',
});
}
// 显示上传文件列表
this.setState({
fileList: info.fileList,
});
// minio config
minioConfig(services);
//client-version-file这个桶是是事先在minio上创建好的
connectionStatus('client-version-file', err => {
// 连接失败会返回err
if (err !== null && fileList.length === 0) {
this.setState({
fileList: [],
});
message.warning('存储服务器连接失败');
return false;
}
// 限制只能上传三个文件
if(info.fileList.Length > 1) {
message.warn('一个版本只能上传一个文件');
return false;
}
// 限制上传文件的类型
if (info.file.name.index0f('.apk') === -1){
message.warn('必须上传以.apk为后缀的文件');
return false;
}
// 上传成功提示
if (info.file.status === 'done' && fileList.Length ===1){
checkedAndUpLoad('client-version-file', info, res => {
// 输出url
message.success(`${info.file.name}文件上传成功`);
this.setstate({
filePath:res,
});
});
} else if (info.file.status === 'error') {
message.error(`${info.file.name}文件上传失败`);
}
});
};
// render
// render() {
// // 上传文件 调用minio进行上传
// const uploadProps = {
// name: 'file',
// accept: 'apk',
// headers: {
// authorization: 'authorization-text',
// },
// fileList,
// onChange: this.onChange,
// };
// return (
// <Upload.Dragger>
// <p className="antd-upload-drag-icon">
// <Icon type="inbox" />
// </p>
// <p className="antd-upload-text">见文件拖拽到此处,或者点击上传</p>
// </Upload.Dragger>
// )
// }
// 下载文件
downloadFile =(url) => {
const { clientVersion: { services } } = this.props;
const fileName = url.substring(url.lastIndex0f('/') + 1);
Let size =0;
const list = new Array();
minioConfig(services);
// download( bucketName fileName callback)
download('client-version-file', fileName, (err,datastream)=>{
if (err){
return message.warn(content: '存储服务器连接失败');
}
message.success( content: '已开始下载,请稍后');
dataStream.on('data' , (chunk)=>{
size +=chunk.Length;
List.push(chunk);
});
dataStream.on('end', () =>
const u8arr =new Uint8Array(size);
Let u8arrindex= 0;
for (Let i=0; i<list.Length; i++) {
for (Let j = 0; j < list[i].length; j++) {
u8arr[u8arrindex] = list[i][j];
u8arrindex+=1;
}
}
Let fileType = '';
switch (fileName.substring(fileName.lastIndex0f('.') +1)) {
case 'apk':
fileType = 'application/vnd.android.package-archive' ;
}
const file = new File( fileBits: [u8arr], fileName: '', options: { type: fileType });
const blob = new Blob( blobParts: [file]);
const Link = document.createElement( tagName: 'a');
Link.href =window.URL.createobjectURL(bLob);
Link.download = url.substring(url.lastIndex0f('/') +1);
Link.click();
window.URL.revokeObjectURL(Link.href);
});
dataStream.on('error', (err) => {
console.Log(err);
});
});
};
/*
* minio.js
* */
// 上传文件需要的配置
const Minio = require('minio');
const stream = require('stream');
// 你的minio配置信息
Let minioClient = {};
// 在页面调用,先连接服务区
export function minioConfig(confiq){
minioClient=new Minio.Client(confiq);
}
// base64转blob
export function toBlob(base64Data) {
Let byteString = base64Data;
if (base64Data.split(',')[@].index0f('base64') >= 0) {
byteString = atob(base64Data.split(',')[1]); // base64 解码
}else{
byteString = unescape(base64Data.split(',')[1]);
}
// 获取文件类型
const mimeString = base64Data.split(';')[@].split(':')[1]; // mime类型
// ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区
// let arrayBuffer =new ArrayBuffer(byteString.length) // 创建缓冲数组
// Let uintArr =new Uint8Array(arrayBuffer) // 创建视图
const uintArr = new Uint8Array(byteString.Length); // 创建视图
for (Let i = 0; i < byteString.Length; i += 1){
uintArr[i] =byteString.charCodeAt(i);
}
// 生成blob
const blob =new Blob( blobParts:[uintArr], options:{
type:mimeString,
});
// 使用 Blob 创建一个指向类型化数组的URL,URL.createObjectURL是new BLob
// 文件的方法,可以生成一个普通的url,可以直接使用,比如用在img.src上
return blob;
}
/*上传文件
*@param {*} bucketName 桶名
*@param {*} info info为antd上传组件的info
*@param {*} callback 回调函数,返回下载url
*/
export function uploadFile(bucketName,info,callback) {
// 获取文件类型及大小
const fileName = info.file.name;
const mineType = info.file.type;
const filesize = info.file.size;
// 参数
const metadata = {
'content-type': mineType,
'content-Length': fileSize,
};
// 将文件转换为minio可接收的格式
const reader = new FileReader();
reader.readAsDataURL(info.file.originFile0bj);
reader.onLoadend = e => {
const dataurl = e.target.result;
// base64转blob
const blob = toBlob(dataurl);
// blob转arrayBuffer
const reader2 = new FileReader();
reader2.readAsArrayBuffer(blob);
reader2.onload = ex => {
// 定义流
const bufferStream = new stream.PassThrough();
// 将buffer写入
bufferStream.end(Buffer.from(ex.target.result));
// 上传
minioClient.putobject(bucketName, fileName, bufferStream, fileSize, metadata, err => {
console.Log(err);
if (err == null) {
// 获取url
minioClient.presignedGetobject(bucketName, fileName, 24 * 60 * 60, (err1, presignedUrl) => {
console.Log(err1);
if (err1) return;
// 将数据返回
callback(presiqnedUrl);
});
}
});
};
};
}
// 先判断桶是否存在,如果可确保捅已经存在,则直接调用upload方法
export function checkedAndUpload(bucketName, info, callback){
minioClient.bucketExists(bucketName, err => {
if(err){
minioclient.makeBucket(bucketName, 'us-east-1', err1 => {
if(err1) {
consle.error(`${info.file.name}文件上传失败`);
return;
}
uploadFile(bucketName,info, callback);
});
}else {
uploadFile(bucketName, info, callback);
}
});
}
// 先判断桶是否存在,如果确保桶已经存在,则直接调用upload方法
export function connectionStatus(bucketName, callback) {
minioClient.bucketExists(bucketName, err => {
console.Log(err);
callback(err);
});
}
export function download(bucketName, fileName, callback) {
minioClient.getobject(bucketName, fileName, (err, dataStream) => {
callback(err, dataStream);
});
}