上传:
遇到的问题:
- 动态赋值 上传的地址action 取值总是慢一步,拿到的是上次的值。
解决方案:
针对问题1:采用延时,目前使用的是 nextTick
代码部分:单文件上传
// template
<template>
<el-upload
ref="attachmentRef"
drag
accept=".jpg,
.jpeg,
.png,
.gif,
.rar,
.txt,.zip,.doc,.ppt,.xls,.xlsx,.docx,.pdf,.JPG,.JPEG,.PDF"
:headers="headers"
:data="{extension: extension}"
:action="buildUploadUrl"
:file-list="fileList"
:auto-upload="false"
:before-upload="handleBeforeUpload"
:on-change="handleChange"
:on-success="handleSuccess"
:on-error="handleError"
:on-remove="handleRemove"
>
<i class="el-icon-upload" />
<div class="el-upload__text">
将文件拖到此处,或 <em>点击上传</em>
</div>
</el-upload>
</template>
// data
data () {
return {
headers: {}, // 可放置接口所需要的 token
fileList: [], // 已上传的文件列表
extension: '', // 上传文件的后缀名
buildUploadUrl: '', // 接口地址
extension: '' // 文件后缀名
}
},
// methods
methods: {
// 处理文件回显,可在 created 里调用该方法
handleEditFileList () {
this.fileList = [] // 替换为 后端返回的数据
},
handleBeforeUpload (file) {
// 校验格式
let allowType = ['jpg',
'png',
'rar', 'txt', 'zip', 'doc', 'ppt', 'xls', 'xlsx', 'pdf', 'docx', 'gif']
let testMsg = file.name.substring(file.name.lastIndexOf('.') + 1) // 文件后缀名
const isAllow = allowType.includes(testMsg)
if (!isAllow) {
this.$message({
message: '不支持当前上传文件的格式!',
type: 'warning'
})
return false
}
// 校验文件大小。不能大于 5M
let maxSize = 5
let isLessThanMaxSize = file.size / 1024 / 1024 < Number(maxSize)
if (!isLessThanMaxSize) {
this.$message.error(`附件大小不能超过 ${maxSize}MB!`)
}
return isLessThanMaxSize
},
handleChange (file) {
if (file.status === 'ready') {
// 准备上传
this.extension = file.name.split('.').pop() // 文件后缀
this.buildUploadUrl = url + `?extension=${this.extension}` // 接口地址拼接文件后缀
// 这里记录一下坑
// 如果不用 nextTick,action总是慢一步,第一次上传接口地址就为空
// 因为需要动态获取的 文件后缀,如果直接上传,action 总是上一次的值(第二次选的txt还是用的第一次的 png)
// submit 方法比 action赋值快一步,这里做下延时
// 延迟
this.$nextTick(() => {
this.$refs.attachmentRef.submit()
})
}
},
handleSuccess (response, file) {
if (!response.isOk) {
this.$refs.attachmentRef.clearFiles()
this.$message.error(response.message || '上传失败~')
return
}
this.url = response.content.url
this.id = response.content.id
this.fileList = [file]
},
handleError () {
this.$refs.attachmentRef.clearFiles()
this.$message.error('上传附件失败~')
},
handleRemove (file) {
if (file.status === 'success') {
this.url = ''
this.id = null
}
}
}
下载:
遇到的问题:
- <a href="url" download="xxx.txt">下载</a> 遇到 文本类型 的文件下载不了。
- window.location.href = url 下载方式,遇到 图片、文本、pdf 类型的文件会直接打开,不会下载。
- createObjectURL() 的时候,可能后端返回的直接就可以用,不用再 new Blob[res.data] 了。
- 如:直接 createObjectURL(res.data),不用 createObjectURL(new Blob([res.data]))
尝试的解决方式:
- 采用 axios 的读取文件的方式下载,注意传 responseType: 'blob
-
handleDownUrl () { if (this.url) { // 后端返回的是 http,网站是 https,不替换会造成跨域,如果一致,可将这段删除 let locationUrl = '' if (location.protocol === 'https' || location.protocol === 'https:') { locationUrl = this.url.replace('http://', 'https://') } else { locationUrl = this.url } axios.get(locationUrl, { responseType: 'blob' }).then(res => { let blob = res.data let url = window.URL.createObjectURL(blob) let a = document.createElement('a') a.style.display = 'none' a.href = url a.download = this.value.url.split('/').pop() document.body.appendChild(a) a.click() window.URL.revokeObjectURL(a.href) document.body.removeChild(a) }) } }
先后尝试了,a链接下载、window.location.href 下载,均不行,换了上述以为行了,于是发到了测试环境测试,测试环境也测过了,以为万事大吉了。
-
上线
报了一个大错误,麻了
应该还是跨域的问题,因为紧急情况,替换了 复制链接(vue-clipboard2) 自行到浏览器下载的方案。
大家如果有解决方案,欢迎交流~