一文搞懂element-ui的文件上传
- 文件上传逻辑
携带token
上传文件到文件服务器,上传胜利服务器返回体里蕴含fileId
和fileName
,上传失败返回失败code
, - 文件下载逻辑
依据fileId
调接口获取二进制流文件,依据fileName
的后缀获取文件类型,把二进制文件依据文件类型生成文件。 其余逻辑
- 文件上传前需判断上传文件类型(文件后缀)及文件大小是否超限,简略不做阐明
碰到问题如下
问题 1.文件上传须要携带 token,并搁置于 header 里
解决方案;
应用el-upload
提供的header
即可
<el-upload :headers="headers" />
data(){ return { headers:{token:"111"} }}
问题 2.图片预览时如果图片不存在可能会返回二进制的 json 文件流,须要非凡解决
判断预览时返回的二进制流,分状况解决
handlePreview(file) { // console.log('要预览的文件是:', file) // 获取服务端返回的文件id和文件名 const fileId = file.response.body.fileId const fileName = file.response.body.fileName axios.post( this.DOWNLOAD_URL, { body: { fileId: fileId } }, { // 设置axios的headers和返回数据类型 headers: this.headers, responseType: 'blob' } ) .then(res => { // 如果文件未找到还是可能会返回二进制格局的json信息,须要进行解决 // 失常状况下会返回须要的二进制文件 if (this.handleMessage(res)) { // 解决失常状况的二进制文件 var fileType = this.getFileType(fileName) if (fileType === 'image') { this.downImage(res.data, fileName) } else { console.info('非图片格式暂无奈预览') } } }) }, handleMessage(res) { // 未解决过的response对象,如果为失常的二进制流文件返回true,如果为二进制的json文件则返回false并展现json内容 if (res.data && res.data.type) { if (res.data.type === 'application/octet-stream') { // 失常的二进制流文件 return true } else if (res.data.type === 'application/json') { // 异样的二进制的JSON文件 const reader = new FileReader() reader.readAsText(res.data, 'utf-8') reader.onload = e => { const result = JSON.parse(reader.result) const message = '下载资源文件失败' + reader.result console.error('下载资源文件失败:', result) this.$message({ message: message, type: 'error', duration: 5 * 1000 }) } return false } } else { console.error( '函数入参response对象应该是一个残缺的对象,应该蕴含data.type属性' ) } }, getFileType(fileName) { // 更多文件类型 参考 https://www.cnblogs.com/zhongcj/archive/2008/11/03/1325293.html const arr = fileName.split('.') const len = arr.length let str = '' if (len > 1) { const allowedImageType = this.allowedImageType ||['jpg','jpeg','png'] const allowedVideoType = this.allowedVideoType || ['mp4'] const fileType = arr[arr.length - 1].toLocaleLowerCase() if (allowedImageType.includes(fileType)) { str = 'image' } else if (allowedVideoType.includes(fileType)) { str = 'video' } } return str }, downImage(blobData, fileName) { const blob = new Blob([blobData], { type: 'image/jpeg' }) const reader = new FileReader() reader.readAsDataURL(blob) reader.onload = e => { const url = URL.createObjectURL(blob) // 取到url,间接在页面展现即可 } },
问题 3.el-upload 组件展现为上传胜利实际上传失败问题
问题产生起因:element-ui
里upload
组件是依据httpCode
来判断的,如果为httpCode<200||httpCode>=300
则判断为上传失败,其余状况则标记为上传胜利。
而开发过程却是不解决httpCode
而是依据responseBody
里的code
字段进行判断,尽管我也感觉通过httpCode
更适合,然而碰到很多状况都是通过响应体里的code
来判断的(难不成是因为后端共事不晓得怎么解决httpCode
?)
handleSuccess(res, file, fileList) { // 上传胜利函数的res是responseBody的body体 // 解决element-ui认为上传胜利(他是通过httpCode为200断定为胜利的),实际上传失败状况(通过responseBody判断) if (res.code && res.code !== 0) { // 上传不胜利给出提示信息 this.$message({ message: res.message || 'error', type: 'error', duration: 5 * 1000 }) this.$nextTick(function() { // 移除上传失败的文件,code为0即为胜利 const successFileList = fileList.filter(ele => { return ele.response.code + '' === '0' }) // 从新设置列表为正确的列表 // this.fileList = successFileList // 假上传胜利时也须要进行一次解决 this.$emit('my-update', successFileList) }) }},
问题 4.如何在包装 el-upload 的自定义组件里获取到最新的已上传的文件列表
应用自定义的v-model
解决在组件最外层获取已上传的文件列表
// 自定义组件内,设置v-modelexport default { model: { prop: 'fileList', event: 'my-update', }, props: { // element-ui上传组件的文件列表数组 fileList: { type: Array, default() { return [] }, }, }, methods: { // 监听ele-upload的change事件 依据文档仅增加文件、上传胜利和上传失败时都会被调用 handleChange(file, fileList) { // console.log('文件发生变化', file, fileList) this.$emit('my-update', fileList) }, // 删除文件后须要同步触发下事件 handleRemove(file, fileList) { const fileId = file.response.body.fileId // console.log('执行删除事件,要删除的文件id', fileId, fileList) const selectedFileList = fileList.filter(ele => { return fileId !== ele.response.body.fileId }) // console.log('删除后文件列表:', selectedFileList) this.$emit('my-update', selectedFileList) }, // 同时假上传胜利时也须要进行一次解决 },}
<!-- 父组件里应用 --> <upload-box v-model="uploadFileList" />