最近在使用Aidex-Sharp前端开源框架,发现文件上传没有,想着自己通过官网写一个,没想到发现了些问题,并附上解决得方法。
问题:
a-upload组件没有专门针对上传成功得回调,只有一个......
然后紧接着无数个问题开始了。
1、无论上传成功或者失败,file.status永远为uploading.
2、通过beforeUpload,做的一系列校验,该方法返回false,按照官网应该停止上传了,但是还是根本拦不住,还上上传了。
3、判断不了是否成功上传,判断不了成功后得url等。
进入正题
解决办法不唯一
但是该方法可以。是通过自定义得上传行为实现。
customRequest | 通过覆盖默认的上传行为,可以自定义自己的上传实现 |
具体实现
一、目录结构及部分代码截图
二、页面调用ImageUpload组件
在需要使用得页面按需要引入然后调用即可,数量、问价文件类型、文件大小等限制
import ImageUpload from '@/components/ImageUpload'
<ImageUpload v-model="form.imgId" :limit='3' :fileType="fileType"/>
三、给出默认值
四、完美效果
五、删除图片
六、完整代码
<template>
<div class="clearfix">
<a-upload
:action="uploadImgUrl"
:headers="headers"
:list-type="type === 'image' ? 'picture-card' : 'picture'"
:file-list="fileList"
:before-upload="beforeUpload"
:customRequest="customRequest"
@preview="handlePreview"
@change="handleChange"
>
<div v-if="fileList.length < limit">
<a-icon type="plus" />
<div class="ant-upload-text">
上传
</div>
</div>
</a-upload>
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
<img alt="example" style="width: 100%" :src="previewImage" />
</a-modal>
</div>
</template>
<script>
import axios from 'axios'
import storage from 'store'
import { ACCESS_TOKEN } from '@/store/mutation-types'
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => resolve(reader.result)
reader.onerror = error => reject(error)
})
}
export default {
name: 'FileUpload',
props: {
// 默认值
value: [String, Object, Array],
// 文件类型
type: {
type: String,
default: 'image'
},
// 大小限制(MB)
fileSize: {
type: Number,
default: 5
},
// 个数限制
limit: {
type: Number,
default: 5
},
// 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => ['png', 'jpg', 'jpeg']
}
},
components: {
},
data() {
return {
uploadImgUrl: process.env.VUE_APP_BASE_API + '/common/upload',
headers: {
Authorization: 'Bearer ' + storage.get(ACCESS_TOKEN)
},
previewVisible: false,
previewImage: '',
fileList: []
}
},
watch: {
value: {
handler(val) {
if (val) {
let temp = 1
// 首先将值转为数组
const list = Array.isArray(val) ? val : this.value.split(',')
// 然后将数组转为对象数组
this.fileList = list.map(item => {
if (typeof item === 'string') {
item = { name: item, url: item, status: 'done' }
}
item.uid = item.uid || new Date().getTime() + temp++
return item
})
} else {
this.fileList = []
return []
}
},
deep: true,
immediate: true
}
},
methods: {
beforeUpload(file) {
// 校检文件类型
if (this.fileType) {
let fileExtension = ''
if (file.name.lastIndexOf('.') > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
}
const isTypeOk = this.fileType.some((type) => {
if (file.type.indexOf(type) > -1) return true
if (fileExtension && fileExtension.indexOf(type) > -1) return true
return false
})
if (!isTypeOk) {
this.$message.error(`文件格式不正确, 请上传${this.fileType.join('/')}格式文件!`)
return false
}
}
// 校检文件大小
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize
if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
return false
}
}
return true
},
handleCancel() {
this.previewVisible = false
},
async handlePreview(file) {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj)
}
this.previewImage = file.url || file.preview
this.previewVisible = true
},
// 自定义上传,可以自定义上传接口,不用通过action属性,还是非常灵活的
customRequest(file) {
// file 是上传的文件 其内容会在放在下面截图中
// 后端需要接受的参数是 formData数据,
const form = new FormData()
form.append('file', file.file)
// uploadFile 我自己的接口
this.uploadFile(form).then(res => {
if (res.status === 200) {
this.$message.success('上传成功')
var fileItem = { name: res.data.fileName, uid: new Date().getTime() + 121, url: res.data.url, status: 'done' }
this.fileList.push(fileItem)
var toString = this.listToString(this.fileList)
this.$emit('input', toString)
} else {
this.$message.error('上传失败')
}
})
},
// 设置好头部
uploadFile (parameter) {
return axios({
url: this.uploadImgUrl,
method: 'post',
headers: { 'Content-Type': 'multipart/form-data', 'Authorization': this.headers.Authorization },
data: parameter
})
},
// 对象转成指定','字符串分隔
listToString(list, separator) {
console.log(list)
let strs = ''
separator = separator || ','
for (var i in list) {
var url = list[i].url
strs += url + separator
}
return strs !== '' ? strs.substr(0, strs.length - 1) : ''
},
async handleChange (info) {
if (info.file.status === 'removed') {
this.$message.success('删除成功')
this.fileList = info.fileList
var toString = this.listToString(this.fileList)
this.$emit('input', toString)
}
}
}
}
</script>
<style>
/* you can make up upload button and sample style by using stylesheets */
.ant-upload-select-picture-card i {
font-size: 32px;
color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
color: #666;
}
</style>
如果有用,欢迎关注~~~