解决 Element-ui plus 的upload组件上传文件时没有携带 data 的问题。
今天使用自己的文件资源管理器 ( 差不多就是自己搭的一个基于 oss 的网盘 ) 的时候出现了上传失败的问题 。排查问题发现表单数据只有一个 file 没有携带签名 callback 等信息。
然后怀疑是 element-ui 的这个 upload 组件在 vue3 组合式写法中可能会出问题。查看了 element-ui 的框架源码,没有发现将 props 里面的 data 加入 formData 的逻辑, 看起来就是简单的 uploadRef.upload(raw)
function submit() {
uploadFiles.value.filter(({ status }) => status === "ready").forEach(({ raw }) => {
var _a;
return raw && ((_a = uploadRef.value) == null ? void 0 : _a.upload(raw));
});
}
这里没有怀疑自己的问题直接找elemenut-ui的问题,是因为附加表单数据这个操作本身过于简单, 只要 el-upload 组件的 data 属性有值就ok。 我打印了 data 确实有值,并且 data 是绑定了一个 ref({}) 声明的响应式对象
<script setup>
import { ref } from "vue";
const uploadData = ref({})
uploadData.value = {test:'it is ok!'}
</script>
<template>
<el-upload :data="uploadData"></el-upload>
</template>
最后的解决方法是自己实现了上传逻辑:
const uploadUrl = ref("")
// 这里为了同时上传多个文件,uploadData 使用 file 的 uid 区分不同文件。
const uploadData = ref({})
async function fileUpload(option) {
let { file } = option;
uploadData.value[file.uid].append('file', file)
let res = await axios.post(uploadUrl.value, uploadData.value[file.uid])
if (res) {
delete uploadData.value[file.uid]
onFileUploadSuccess(res.data)
}
}
验签逻辑:
async function handleBeforeUpload(file) {
try {
uploadData.value[file.uid] = new FormData()
let verificationData = Object.assign({}, { name: file.name }, props.data)
const res = await axios.create({
baseURL: props.host,
headers: {
Authorization: authStore.tokenType + ' ' + authStore.accessToken,
}
}).post(props.ossSignatureVerification, verificationData)
const response = res.data
uploadUrl.value = response.host
// 组装自定义参数「如果要自定义回传参数这段代码不能省略」
if (response['callback-var'] && Object.keys(response['callback-var']).length) {
for (const [key, value] of Object.entries(response['callback-var'])) {
uploadData.value[file.uid].append([key], value)
}
}
uploadData.value[file.uid].append('policy', response.policy)
uploadData.value[file.uid].append('OSSAccessKeyId', response.accessid)
uploadData.value[file.uid].append('signature', response.signature)
uploadData.value[file.uid].append('host', response.host)
uploadData.value[file.uid].append('callback', response.callback)
uploadData.value[file.uid].append('key', response.dir + '/' + file.name)
} catch (error) {
errorMsg('获取上传配置失败')
}
}
模板代码:
<template>
<el-dialog v-model="props.visible" :title="props.title" width="500px" @close="$emit('close')">
<div class="w-full h-full overflow-auto" style="height: 300px">
<el-upload drag multiple
:before-upload="handleBeforeUpload" class="mx-4" :http-request="fileUpload">
<el-icon class="el-icon--upload" style="height: 150px">
<upload-filled />
</el-icon>
<div class="el-upload__text">
将文件拖动到这里或者<em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip">文件不能超过100MB</div>
</template>
</el-upload>
</div>
</el-dialog>
</template>
本作品采用《CC 协议》,转载必须注明作者和本文链接