解决 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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!