需求:选择文件后不自动上传,先预览,也可下载,最后和表单其他参数一起保存提交调接口。
//上传组件
<el-upload
ref="upload"
action="#"
:on-remove="handleRemove"
:http-request="submitUpload"
:limit="1"
:accept="acceptStr"
:before-upload="beforeUpload"
:on-exceed="onExceed"
:file-list="fileList"
>
<el-button type="primary" size="mini">选择文件</el-button>
</el-upload>
//预览小图,点击出现弹框
<img
:src="localUrl"
:title="imgTitle"
width="200"
height="200"
style="cursor: pointer"
v-on:click="previewBtnClick"
/>
//弹框,查看大图,或者播放视频
<el-dialog
title="预览"
:visible.sync="previewDialogVisible"
width="50%"
append-to-body
style="background: unset"
class="previewDialog"
>
<img
:src="localUrl"
alt=""
width="500"
height="500"
v-if="uploadType==='image'"
/>
<video
:src="localSrc"
controls
width="100%"
height="500px"
autoplay
muted
loop
v-else-if="uploadType==='video'"
id="video"
></video>
</el-dialog>
//提示用户只能选择一个文件
onExceed() {
this.$message.error('一次只能上传一个文件');
},
//当删除上传时,把预览小图还原成默认图片,上传类型还原
handleRemove() {
this.localUrl = this.previewImg;
this.uploadType = '';
},
//要求用户,先选择好类型,再选择文件,如果用户在选择文件时把选择类型变为*时,选择不符合当前类型的文件,提示用户
beforeUpload(file) {
if (!this.acceptStr) {
this.$message.error('请先选择实体类型');
return false;
}
let acceptArr = this.acceptStr.replace(/\./g, '').split(',');
if (!acceptArr.includes(file.name.split('.')[1].toUpperCase())) {
this.$message.error('请选择符合实体类型的文件');
return false;
} else {
return true;
}
},
//上传 保存文件对象用于传给后端,通过FileReader对象,得到url用于图片和视频
submitUpload(params) {
this.fileObj = params.file;
this.fileName = this.fileObj.name;
const file = params.file;
const type = file.type.split('/')[0];
if (type === 'image') {
this.uploadType = 'image';
let imageReader = new FileReader();
imageReader.readAsDataURL(file);
imageReader.onload = () => {
this.localUrl = imageReader.result;
this.imgTitle = '点击预览';
};
} else if (type === 'video') {
this.uploadType = 'video';
let videoReader = new FileReader();
videoReader.readAsDataURL(file);
videoReader.onload = () => {
this.localUrl = `${ctxPath}/static/wjImg/${this.uploadType}.jpeg`;
this.localSrc = videoReader.result;
this.imgTitle = '点击预览';
};
} else {
this.uploadType = 'other';
this.localUrl = `${ctxPath}/static/wjImg/default.jpg`;
this.imgTitle = '点击下载';
}
},
//当用户点击预览大图时,预览图片和播放视频,其他类型如(word)进行下载
previewBtnClick() {
if (['image', 'video'].includes(this.uploadType)) {
this.previewDialogVisible = true;
} else if (this.uploadType === 'other') {
this.downloadFile(this.fileObj, this.fileName);
}
},
//下载功能,如(word,excel,pdf)
downloadFile(file, name) {
let downloadElement = document.createElement('a');
// // 创建下载的链接
let href = window.URL.createObjectURL(file);
downloadElement.href = href;
// 下载后文件名
downloadElement.download = name;
document.body.appendChild(downloadElement);
// 点击下载
downloadElement.click();
// 下载完成移除元素
document.body.removeChild(downloadElement);
// 释放掉blob对象
window.URL.revokeObjectURL(href);
},
传给后端时,选择formData形式:
const form = new FormData();
form.append('uFile', this.fileObj);
//把其他参数变成json字符串传给后端,最后设置响应头。
form.append('paramJsonStr', JSON.stringify(params));
axios({
url: '/apiTrainIetm/commonDocument/insertCommonDocument',
method: 'post',
data: form,
headers: {
'Content-Type': 'multipart/form-data',
},
回显,后端返回文件流,前端通过blob接收:
在请求时,设置请求的 responseType: 'blob',
const res = await axios(
'/apiTrainIetm/commonDocument/selectFileByFilePath',
{
params: {
filePath: comFilePath,
},
responseType: 'blob',
}
);
let blob = res.data;
//把blob转换为file对象,因为后端需要的是这个对象。
this.fileObj = new File([blob], this.fileName);
let href = window.URL.createObjectURL(blob);
//解析blob类型转换为blob的url,用于图片显示和播放视频
this.fileList.push({
name: this.fileName,
url: href,
});
if (this.docTypeList.includes(this.extension.toUpperCase())) {
this.uploadType = 'other';
this.localUrl = `${ctxPath}/static/wjImg/default.jpg`;
} else if (this.videoTypeList.includes(this.extension.toUpperCase())) {
this.uploadType = 'video';
this.localUrl = `${ctxPath}/static/wjImg/video.jpeg`;
this.localSrc = href;
} else {
this.uploadType = 'image';
this.localUrl = href;
}