前言
最近经常用到上传组件,总结一下它的用法,做成一个组件供随时使用。
1. 前置需要
搭建好oss服务器
后台能够接收文件上传服务器,并返回文件对应的id
2. 文件上传
2.1 分析需求
- 能够上传文件(好像没说一样)
- 能够回显并下载文件
- 能够编辑已上传的文件
- 能够检测文件是否是符合要求(大小,格式)
2.2 根据功能写出需要的配置
以下是完整的配置项
<a-upload
:beforeUpload="beforeFileUpload" // 上传前的回调,作用是判断文件格式、大小等等
:defaultFileList="defaultFileList" // 初始文件列表,用于回显
:headers="headers" // 上传请求的请求头,存着authorization值
:multiple="true" // 支持多选上传
:remove="handleFileRemove" // 上传列表删除回调,文件的删除需要自己实现
@change="handleChange" // 上传的回调,分为三种
action="/api/storage/upload" // 对应后台api
style="width: 60%"
>
<a-button>
<a-icon type="upload"/>
上传
</a-button>
</a-upload>
介绍一下@handleChange
回调,返回参数info
中存储着 file
和 fileList
两个参数
file
: 存储着当前操作的文件信息
response
是后台上传返回的结果
status
是我们判断上传上传中、完成、失败的参数

fileList
: 存储着当前已上传的文件,与显示已上传列表相关联
若想初始化回显文件时,需要配置以下参数(第一个)
uid
: 文件的id
name
: 文件名称
status
: 文件的状态,默认为done
即可
url
: 文件的下载链接(这里的第二个文件是刚上传的,默认没有下载链接)

2.3 js部分
2.3.1 data
部分
主要存储的是请求头
和 回显用的文件列表(这里只存储了4个参数,可以按照实际需要增删)
data () {
return {
headers: {
authorization: ''
},
defaultFileList: [
{
uid: '1',
name: '测试',
status: 'done',
url: 'sss'
}
]
}
}
2.3.2 handleChange
上传回调
文件上传都会调用这个函数
info.file.status
可能为 uploading
、done
、error
分别对应着上传中
,完成
,错误
defaultFileList
维护的是当前已上传的文件,最后提交使用,这里只存储了4个参数,可以按照实际需要增删
handleChange (info) {
const file = info.file
const status = info.file.status
if (status === 'done') { // 完成
this.$message.success('图片上传成功...')
const res = file.response.data // 上传后台返回的结果
const item = {
uid: res.newFileName,
name: res.filename,
status: 'done',
url: res.url
}
this.defaultFileList.push(item)
} else if (status === 'error') { // 错误
this.$message.error(`${info.file.name} 文件上传失败`)
}
},
2.3.3 handleFileRemove
删除文件回调
当点击了文件列表删除时的回调

handleFileRemove (file) {
const name = file.name
this.defaultFileList = this.defaultFileList.filter(item => {
if (name !== item.name) return item
})
}
2.3.4 beforeFileUpload
上传前回调
判断文件的类型,大小等等,达到上传前判断是否符合要求
ps: 这里直接返回false
,并没有达到不能终止上传的结果,通过Promise
返回reject()
实现的
beforeFileUpload (file) {
return new Promise((resolve, reject) => {
const isJPG = file.type === 'image/jpeg'
if (!isJPG) {
this.$message.error('您只能上传jpg文件')
return reject(false)
}
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('文件大小不能大于2MB')
return reject(false)
}
this.$message.info('文件正在上传中...')
return resolve(true)
})
}
2.4 根据文件上传,写成了图片上传
点击可查看大图

<a-upload
:beforeUpload="beforeImageUpload"
:defaultFileList="defaultImageList"
:headers="headers"
:remove="handleImageRemove"
@change="handleImageChange"
@preview="handleImagePreview"
action="/api/storage/upload"
listType="picture-card"
style="width: 60%"
>
<div v-if="defaultImageList.length < 2">
<a-icon :type="imageLoading ? 'loading' : 'plus'"/>
<div class="ant-upload-text">上传</div>
</div>
</a-upload>
<a-modal :footer="null" :visible="previewVisible" @cancel="handleImageCancel">
<img :src="previewImage" alt="example" style="width: 100%"/>
</a-modal>
data () {
return {
defaultImageList: [
{
uid: '1',
name: 'Emilia',
status: 'done',
url: 'http://boot.demo.7326it.club/storage/2020021200028.jpg'
}
],
imageLoading: false,
previewVisible: false,
previewImage: ''
}
}
handleImageChange (info) {
const file = info.file
const status = info.file.status
if (info.file.status === 'uploading') {
this.imageLoading = true
return
}
if (status === 'done') {
this.$message.success('图片上传成功...')
this.imageLoading = false
const res = file.response.data
const item = {
uid: res.newFileName,
name: res.filename,
status: 'done',
url: res.url
}
this.defaultImageList.push(item)
} else if (status === 'error') {
this.$message.error(`${info.file.name} 图片上传失败`)
}
},
beforeImageUpload (file) {
return new Promise((resolve, reject) => {
const isJPG = file.type === 'image/jpeg'
if (!isJPG) {
this.$message.error('您只能上传jpg文件')
return reject(new Error('您只能上传jpg文件'))
}
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('文件大小不能大于2MB')
return reject(new Error('文件大小不能大于2MB'))
}
this.$message.info('文件正在上传中...')
return resolve(true)
})
},
handleImageRemove (file) {
const name = file.name
this.defaultImageList = this.defaultImageList.filter(item => {
if (name !== item.name) return item
})
},
handleImagePreview (file) {
this.previewImage = file.url || file.thumbUrl
this.previewVisible = true
},
handleImageCancel () {
this.previewVisible = false
}
2.5 完整上传代码(文件上传 + 图片上传)
<template>
<a-card :bordered="false" title="上传">
<a-row style="margin-bottom: 20px">
<a-col :span="4">
<div class="example-side">
demo1:上传文件
</div>
</a-col>
<a-col :span="8">
<div class="example-side">
<!-----------------------------------------------------------------demo1---start-->
<a-upload
:beforeUpload="beforeFileUpload"
:defaultFileList="defaultFileList"
:headers="headers"
:multiple="true"
:remove="handleFileRemove"
@change="handleChange"
action="/api/storage/upload"
style="width: 60%"
>
<a-button>
<a-icon type="upload"/>
上传
</a-button>
</a-upload>
<!-----------------------------------------------------------------demo1---end-->
</div>
</a-col>
<a-col :span="12" class="example-side-row">
<strong>新上传的是不能下载的,defaultFileList记录了当前上传的文件信息</strong>
{{ defaultFileList }}
</a-col>
</a-row>
<a-row style="margin-bottom: 20px">
<a-col :span="4">
<div class="example-side">
demo2:图片上传
</div>
</a-col>
<a-col :span="8">
<div class="example-side">
<!-----------------------------------------------------------------demo2---start-->
<a-upload
:beforeUpload="beforeImageUpload"
:defaultFileList="defaultImageList"
:headers="headers"
:remove="handleImageRemove"
@change="handleImageChange"
@preview="handleImagePreview"
action="/api/storage/upload"
listType="picture-card"
style="width: 60%"
>
<div v-if="defaultImageList.length < 2">
<a-icon :type="imageLoading ? 'loading' : 'plus'"/>
<div class="ant-upload-text">上传</div>
</div>
</a-upload>
<a-modal :footer="null" :visible="previewVisible" @cancel="handleImageCancel">
<img :src="previewImage" alt="example" style="width: 100%"/>
</a-modal>
<!-----------------------------------------------------------------demo2---end-->
</div>
</a-col>
<a-col :span="12" class="example-side-row">
{{ defaultImageList }}
</a-col>
</a-row>
</a-card>
</template>
<script>
export default {
name: 'UploadBox',
data () {
return {
headers: {
authorization: ''
},
// --------- file-upload----start
defaultFileList: [
{
uid: '1',
name: '测试',
status: 'done',
url: 'sss'
}
],
// --------- file-upload----end
// --------- img-upload----start
defaultImageList: [
{
uid: '1',
name: 'Emilia',
status: 'done',
url: 'http://boot.demo.7326it.club/storage/2020021200028.jpg'
}
],
imageLoading: false,
previewVisible: false,
previewImage: ''
// --------- img-upload----end
}
},
created () {
this.headers.authorization = 'Bearer ' + this.$store.state.user.token
},
methods: {
// ---------------------------------------------file--start--
handleChange (info) {
const file = info.file
const status = info.file.status
if (status === 'done') {
this.$message.success('图片上传成功...')
const res = file.response.data
const item = {
uid: res.newFileName,
name: res.filename,
status: 'done',
url: res.url
}
this.defaultFileList.push(item)
} else if (status === 'error') {
this.$message.error(`${info.file.name} 文件上传失败`)
}
},
handleFileRemove (file) {
const name = file.name
this.defaultFileList = this.defaultFileList.filter(item => {
if (name !== item.name) return item
})
},
beforeFileUpload (file) {
return new Promise((resolve, reject) => {
const isJPG = file.type === 'image/jpeg'
if (!isJPG) {
this.$message.error('您只能上传jpg文件')
return reject(new Error('您只能上传jpg文件'))
}
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('文件大小不能大于2MB')
return reject(new Error('文件大小不能大于2MB'))
}
this.$message.info('文件正在上传中...')
return resolve(true)
})
},
// ---------------------------------------------file--end
// ---------------------------------------------img--start
handleImageChange (info) {
const file = info.file
const status = info.file.status
if (info.file.status === 'uploading') {
this.imageLoading = true
return
}
if (status === 'done') {
this.$message.success('图片上传成功...')
this.imageLoading = false
const res = file.response.data
const item = {
uid: res.newFileName,
name: res.filename,
status: 'done',
url: res.url
}
this.defaultImageList.push(item)
} else if (status === 'error') {
this.$message.error(`${info.file.name} 图片上传失败`)
}
},
beforeImageUpload (file) {
return new Promise((resolve, reject) => {
const isJPG = file.type === 'image/jpeg'
if (!isJPG) {
this.$message.error('您只能上传jpg文件')
return reject(new Error('您只能上传jpg文件'))
}
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('文件大小不能大于2MB')
return reject(new Error('文件大小不能大于2MB'))
}
this.$message.info('文件正在上传中...')
return resolve(true)
})
},
handleImageRemove (file) {
const name = file.name
this.defaultImageList = this.defaultImageList.filter(item => {
if (name !== item.name) return item
})
},
handleImagePreview (file) {
this.previewImage = file.url || file.thumbUrl
this.previewVisible = true
},
handleImageCancel () {
this.previewVisible = false
}
// ---------------------------------------------img--end
}
}
</script>
<style scoped>
.example-side {
display: flex;
flex-direction: row;
padding-left: 50px;
}
.example-side-row {
display: flex;
flex-direction: column;
padding-left: 50px;
}
.example-center {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
</style>