el-form与el-upload结合上传带附件的表单数据(前端篇)
1.写在之前
本文前端采用Vue + element-plus技术栈,前端项目参考yudao-ui-admin-vue3项目与
Geeker-Admin项目。
这篇文章是el-form与el-upload结合上传带附件的表单数据(后端篇)-CSDN博客姐妹篇,后端篇文章主要讲的是后端的实现逻辑,前端篇稍微简单一些,其实最主要的就是封装el-upload组件,供具体的表单组件调用。
2.封装el-upload组件
废话不多说,直接上代码。
选取文件 import { propTypes } from '@/utils/propTypes' import { getAccessToken } from '@/utils/auth' import type { UploadUserFile, UploadProps, UploadRawFile, UploadFile } from 'element-plus' import { downloadFile } from '@/api/infra/file' import download from '@/utils/download' defineOptions({ name: 'UploadFile' }) const message = useMessage() // 消息弹窗 const emit = defineEmits(['update:fileList']) const props = defineProps({ fileList: propTypes.array.def([]), title: propTypes.string.def('文件上传'), updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL), fileType: propTypes.array.def([]), // 文件类型, 例如['png', 'jpg', 'jpeg'] fileSize: propTypes.number.def(500), // 大小限制(MB) limit: propTypes.number.def(5), // 数量限制 autoUpload: propTypes.bool.def(true), // 自动上传 drag: propTypes.bool.def(false), // 拖拽上传 isShowTip: propTypes.bool.def(true), // 是否显示提示 bucket: propTypes.string.def('operation'), //默认存储到operation bucket中 disabled: propTypes.bool.def(false) }) // ========== 上传相关 ========== const uploadList = ref([]) const _fileList = ref(props.fileList) const uploadHeaders = ref({ Authorization: 'Bearer ' + getAccessToken() }) // 监听 props.fileList 列表默认值改变 watch( () => props.fileList, (n: UploadUserFile[]) => { _fileList.value = n } ) // 文件上传之前判断 const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => { if (_fileList.value.length >= props.limit) { message.error(`上传文件数量不能超过${props.limit}个!`) return false } let fileExtension = '' if (file.name.lastIndexOf('.') > -1) { fileExtension = file.name.slice(file.name.lastIndexOf('.')) } const isImg = props.fileType.some((type: string) => { if (file.type.indexOf(type) > -1) return true return !!(fileExtension && fileExtension.indexOf(type) > -1) }) const isLimit = file.size { // 因为后端返回的res经过统一处理拦截 此处需要根据res返回的code判断是否真的上传成功 let code: number = res.code let data = res.data if (code == 200) { let name = data.name //后端生成的文件唯一标识 //前端存储中 如果有response相同的文件,说明有相同内容的文件 需要清楚所有 只保存一个 即本次上传的文件 _fileList.value = _fileList.value.filter((item) => item.name !== name) uploadList.value.push({ name: data.name, url: data.url, response: data.response }) _fileList.value = _fileList.value.concat(uploadList.value) _fileList.value.sort(sortFileList('name')) uploadList.value = [] message.success('文件上传成功') emitUpdateModelValue() } else { message.error('文件上传失败') } } // 文件数超出提示 const handleExceed: UploadProps['onExceed'] = (): void => { message.error(`上传文件数量不能超过${props.limit}个!`) } // 上传错误提示 const excelUploadError: UploadProps['onError'] = (): void => { message.error('导入数据失败,请您重新上传!') } // 删除上传文件 const handleRemove = (file) => { const findex = _fileList.value.map((f) => f.name).indexOf(file.name) if (findex > -1) { _fileList.value.splice(findex, 1) emitUpdateModelValue() } } const handlePreview: UploadProps['onPreview'] = async (uploadFile: UploadFile) => { console.log(123) const res = await downloadFile(uploadFile.response) console.log(res) download.commonFile(res, uploadFile.name) } const emitUpdateModelValue = () => { emit('update:fileList', _fileList.value) } //数组排序 按照名字升序 const sortFileList = (name) => { const rev = 1 return function (a, b) { a = a[name] b = b[name] if (a b) { return rev } return 0 } } .upload-file-uploader { margin-bottom: 5px; } :deep(.el-upload-list) { width: 400px; } :deep(.upload-file-list .el-upload-list__item) { position: relative; margin-bottom: 10px; line-height: 2; border: 1px solid #e4e7ed; } :deep(.el-upload-list__item-file-name) { max-width: 500px; } :deep(.upload-file-list .ele-upload-list__item-content) { display: flex; justify-content: space-between; align-items: center; color: inherit; } :deep(.ele-upload-list__item-content-action .el-link) { margin-right: 10px; }
代码组件个人理解没有什么好讲的。开启自动上传,上传成功拿到后端的数据返回,构造数据,如果有名称相同的文件,全部删除,只使用最新的上传文件数据。上传成功后,更新表单绑定的文件数据。
3.关于文件的下载
这里想要说一下文件的下载,前期看了很多实现,有使用a标签用文件的URL实现下载的,有直接使用window.open(URL)实现的,我在实际下载中,遇到两个问题,第一是遇到浏览器能处理的文件,例如MP4的视频文件,pdf的文本文件,会直接打开,不会下载,第二个问题是下载的名称不能自己指定,按照网上查找的方法指定也不起作用,最后我选择的第二节中代码方法,先获取文件内容,后下载文件。
commonFile: (data: Blob, fileName: string) => { download0(data, fileName, 'application/octet-stream') } const download0 = (data: Blob, fileName: string, mineType: string) => { // 创建 blob const blob = new Blob([data], { type: mineType }) // 创建 href 超链接,点击进行下载 window.URL = window.URL || window.webkitURL const href = URL.createObjectURL(blob) const downA = document.createElement('a') downA.href = href downA.download = fileName downA.click() // 销毁超连接 window.URL.revokeObjectURL(href) }
4.表单使用
先上一段代码,上传的文件类型为file-type规定的文件类型。
附件 这是一些注意消息,比如上传的文件个数,上传的文件类型,上传的文件大小,上传的文件注意事项
5.实际效果展示
6.写在最后
其实感觉前端只要有第二节封装组件的代码,代码一看就一目了然,就是在文件下载时候,多花了一点小心思。本篇文章只是简单笼统的介绍了一下前端实现传文件,具体的表单设计其实有很多立方需要讲,后期的话,如果有时间,会录一个实际效果展示视频,敬请期待。如果有不对的地方,还请看到本篇文章的您不吝赐教。
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理!
部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!
图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!