vue+element UI 实现文件上传
1、带参数上传文件
注意点:
参数通过属性:data = ”params"传递,对象类型。
-
第一次上传没带参数,第二次上传传递的是第一次的参数。解决方案:
在选择文件的时候就设置好参数,而不是在beforeupload的回调函数中设置。
手动上传比较好,给upload 加一个ref
<el-upload
class="upload-area"
drag
:action="`/operation/org/member/data/upload`"
:on-error="handleError"
multiple
:data="uploadParams"
:auto-upload="false"
ref="uploadRef"
@click="handleBeforeUpload"
>
...
const uploadParams = reactive({
configId: '',
});
....
function handleBeforeUpload(): void {
uploadFormRef.value.validate().then(() => {
uploadParams.configId = uploadForm.configId;
});
}
...
function handleUpload(): void {
uploadFormRef.value.validate().then(() => {
uploadRef.value.submit();
closeDialog();
});
}
2、文件上传之前先校验文内容规则是否符合预期,在提交,而且有图标显示校验效果。
由于上传文件校验和提交调用的接口虽然名称不同,但是后端处理的逻辑是一样的,前端选择和处理的文件也是同一个,所以upload组件中的action 属性的URL是不一样的,如果点击varify 或者submit 的时候改变使用计算属性改变URL,实际并不好使用,因为使用了同一个上传组件,提交的URL不一样,但是成功的回调又是同一个,要针对两种场景下的提交做判断,通过点击不同的按钮实现并不科学,因为可能对同一个按钮点击多次,那么何时改变URL变得难以监听。。。
最后解决方式是使用两个upload 组件,除了对应的action 对应的URL不一样之外,其他的都一样就搞定了。。。(ps:一开始想到了这思路,但是觉的不应该让代码复用率这么低——对同一个组件使用两个upload组件,固执的做各种判断,最后代码的鲁棒性极差。。写代码还是需要灵活一点。。。。)
代码如下:
<el-upload
:action="`/operation/upload/check`"
:auto-upload="false"
:on-preview="handlePreview"
:file-list="fileData"
ref="uploadRef"
:on-success="handleSuccess"
:on-error="handleError"
:on-change="handleChange"
:mutiple="false"
@click="handleSelect"
>
<el-button class="btn-select">Select</el-button>
</ks-upload>
<ks-upload
:action="`/operation/upload`"
:auto-upload="false"
:on-preview="handlePreview"
:file-list="fileData"
ref="submitRef"
:on-success="handleSuccess"
:on-error="handleError"
:on-change="handleChange"
:mutiple="false"
@click="handleSelect"
>
</el-upload>
<el-button v-if="hasFile" class="btn-verify" @click="onVerify"> Data Verify</el-button>
</div>
<!-- 显示上传的文件名 校验错误图标 覆盖自动上传的fileList -->
<div v-if="showFile">
<span class="file"> {{ fileName }}</span> <i v-if="varifyErr" class="ks-icon-error"></i>
<i v-if="varifyPass" class="sys-icon-checkbox-circle-fill"></i
></div>
<!-- 展示上传错误信息 -->
<div v-if="varifyErr" class="err-message">
<div v-for="errItem in errorMessage" :key="errItem.message">
{{ errItem.message }}
</div>
</div>
function onVerify(): void {
// 判断当前是校验文件还是提交,接口路径不同
isCheck.value = true;
uploadRef.value.submit();
// 点击文件校验时候会调用handleChange,如果校验之前点击过下载会导致图标无效。
clickFile.value = false;
}
function onSubmit(): void {
if (!varifyPass.value) {
Message.error('please verify the file coorectly!');
return;
}
// uploadRef.value.submit();
submitRef.value.submit(); // 不同的upload组件ref不同
closeDialog();
}
function handleSuccess(data: any, file: any, fileList: any): void {
fileList[0].status = 'ready'; // 校验和提交使用的同一个文件,校验之后还可以提交
if (data.result === 1) {
// 如果是文件校验
if (isCheck.value) {
varifyErr.value = false;
varifyPass.value = true;
isCheck.value = false;
Message.success('Data Verify successfully');
} else {
Message.success('Submit successfully');
}
} else {
Message.error(data.message);
varifyErr.value = true;
varifyPass.value = false;
errorMessage.value = data.data;
}
}
// 点击文件列表中已上传的文件时的钩子,可实现下载
function handlePreview(file?: any): void {
clickFile.value = true;
const URL = window.URL || window.webkitURL;
const fileURL = URL.createObjectURL(file.raw);
// window.open(fileURL); //直接下载,文件名是乱码的
// 让下载的文件名和上传一样
const name = file.name;
const a = document.createElement('a');
a.setAttribute('download', name);
a.setAttribute('target', '_blank');
a.setAttribute('href', fileURL);
a.click();
}