前端上傳文件到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上創(chuàng)建好的
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 = {};
// 在頁面調用,先連接服務區(qū)
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 對象用來表示通用的碌识、固定長度的原始二進制數(shù)據(jù)緩沖區(qū)
// let arrayBuffer =new ArrayBuffer(byteString.length) // 創(chuàng)建緩沖數(shù)組
// Let uintArr =new Uint8Array(arrayBuffer) // 創(chuàng)建視圖
const uintArr = new Uint8Array(byteString.Length); // 創(chuàng)建視圖
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 創(chuàng)建一個指向類型化數(shù)組的URL碾篡,URL.createObjectURL是new BLob
// 文件的方法,可以生成一個普通的url筏餐,可以直接使用开泽,比如用在img.src上
return blob;
}
/*上傳文件
*@param {*} bucketName 桶名
*@param {*} info info為antd上傳組件的info
*@param {*} callback 回調函數(shù),返回下載url
*/
export function uploadFile(bucketName,info,callback) {
// 獲取文件類型及大小
const fileName = info.file.name;
const mineType = info.file.type;
const filesize = info.file.size;
// 參數(shù)
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;
// 將數(shù)據(jù)返回
callback(presiqnedUrl);
});
}
});
};
};
}
// 先判斷桶是否存在魁瞪,如果可確保捅已經(jīng)存在穆律,則直接調用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);
}
});
}
// 先判斷桶是否存在惠呼,如果確保桶已經(jīng)存在,則直接調用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);
});
}