minio文件上传有两种方法:
以上说的两种方法中,第一种方法会把ak,sk暴露给前端,造成一定的安全隐患;所以如果要使用第一种方法,需要向后端请求生成临时的ak,sk;
这边我们实现了第二种方法。
前端代码如下,这种方法的思路是先向后端请求生成presigned-url,然后再通过binary的方式进行文件上传;注意这里有一个小坑,就是上传文件不要使用form-data,否则会在文件加上WebKitFormBoundary前缀,minio生成的presigned-url没有对此进行解析,这种上传方式会导致如.png .mp4的文件打不开。
<template>
<el-upload ref="uploadRef" :http-request="uploadSubmit" :auto-upload="false" v-model:file-list="fileList" :limit="1"
:on-success="onSuccess">
<template #trigger>
<el-button type="primary" style="width: 100px;">select</el-button>
</template>
<el-button type="success" @click="uploadRef.submit()" style="margin-left: 2rem;width: 100px;">upload</el-button>
<div class="demo-progress">
<el-progress :percentage=percent />
</div>
<el-button size="small" type="primary" @click="cancelUpload">取消上传</el-button>
</el-upload>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios';
const uploadRef = ref();
const fileList = ref([]);
let percent = ref(0);
let Cancel = axios.CancelToken.source()
async function uploadSubmit(options) {
console.log(options)
const item = options['file'];
var presignedUrl = ""
var objSize = item.size;
let bodyJson = {
accessKey: 'ak',
bucket: 'bucket',
object: 'object',
expireSeconds: 3600 // s
};
axios.put('/path/uploadUrl', bodyJson).then(res => {
if (res.status == 200) {
presignedUrl = res.data.data
axios({
method: "put",
url: presignedUrl,
data: item, // 重点1,直接将原始二进制流赋给data
headers: {
"Content-Type": "application/octet-stream", // 重点2
},
timeout: 3600000, // ms
onUploadProgress: function (e) {
percent.value = parseInt(e.loaded / objSize * 100);
},
cancelToken: Cancel.token
}).then(res => {
if (res.status == 200) {
console.log('success')
}
}).catch(
err => {
console.log(err)
}
)
}
})
}
const onSuccess = (response, file, fileList) => {
console.log(response);
console.log(file);
console.log(fileList);
}
function cancelUpload() {
Cancel.cancel();
Cancel = axios.CancelToken.source(); // 重新定义cancelToken
}
</script>
<style scoped>
.demo-progress .el-progress--line {
margin-bottom: 15px;
width: 350px;
}
</style>