0%

Vue 中使用 Upload 组件上传图片

vue 中使用 Element 的 upload 组件上传 Excel,大致可以分两种情况

  1. 使用 action 上传到服务器

    如下不讨论使用 action 上传服务器,如需了解可以参考:Vue 中使用 Upload 组件上传 Excel

  2. 使用 axios 上传到服务器

    这里主要阐述如下两种情况

    • 使用 FormData 上传
    • 使用 base64 上传

基础知识(原理)

input file 属性

  • accept:可选择的文件类型,例如:image/*
  • multiple:允许用户选择多个文件

监听 input file 的 onchange 事件,打印 this.files选取的文件集合,每一项就是选择的文件。每一项 files 包含如下属性:

  • lastModified
  • lastModifiedDate
  • name
  • size
  • type

方案1:FormData 上传

将本地数据上传或导入数据库,有时候需要使用 FormData 对象。FormData 接口提供了一种表示表单数据的键值对 key/value 的构造方式,组成一个 queryString 提交到后台

注意:如下直接打印 formData 里面是空的,formData 需要用 get 方法获取值

代码如下:(这个例子是只要导入就会立即上传)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<template>
<el-upload
ref="upload"
multiple
action
:accept="fileType.join(',')"
:http-request="submitUpload"
:before-upload="beforeUpload"
drag
>
<i class="el-icon-upload" />
<div slot="tip" class="el-upload__tip" style="color:red">
提示:仅允许导入“png”、“jpg”、“jpeg”格式文件,且不超过2M!
</div>
</el-upload>
</template>

<script>
import { uploadFile } from '../api/index'
export default {
data() {
return {
fileType: ['image/jpeg', 'image/jpg', 'image/png']
}
},
methods: {
submitUpload(req) {
const formData = new FormData()
const config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
formData.append('file', req.file)
formData.append('filename', req.filename)
uploadFile('url', formData, config)
},
beforeUpload(file) {
const isImg = this.fileType.includes(file.type)
const isLimit = file.size / 1024 / 1024 < 2
if (!isImg) {
this.$message.error('上传图片只能是“png”、“jpg”、“jpeg”格式!')
}
if (!isLimit) {
this.$message.error('上传图片大小不能超过 2MB!')
}
return isImg && isLimit
}
}
}
</script>

方案2:把选择的文件 base64 后上传

有一些小图片可能会采取前端 base64 上传。这里我们使用 H5 FileReader 对象,用 readAsDataURL 将文件转 base64

注意:readAsDataURL 操作是异步的

代码如下:(这个例子是手动点击上传再上传)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<template>
<div>
<el-upload
ref="upload"
action
list-type="picture-card"
:file-list="imgList"
:accept="imgTool.type.join(',')"
:on-change="handleChange"
:on-remove="hadnleRemove"
:auto-upload="false"
>
<i class="el-icon-upload" />
<div slot="tip" class="el-upload__tip" style="color:red">
提示:仅允许导入“png”、“jpg”、“jpeg”格式文件,且不超过2M!
</div>
</el-upload>
<el-button type="success" size="mini" @click="submitUpload">上传到服务器</el-button>
</div>
</template>

<script>
import { uploadFile } from '../api/index'
export default {
data() {
return {
imgTool: {
type: ['image/jpeg', 'image/jpg', 'image/png'],
size: 2 * 1024 * 1024
},
imgList: []
}
},
methods: {
async submitUpload() {
console.log(this.imgList)
const base64Pro = this.imgList.map(file => this.fileReader(file.raw))
const base64List = await Promise.all(base64Pro)
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
base64List.forEach((item, i) => {
const data = {
base64: decodeURIComponent(item),
name: this.imgList[i].name
}
uploadFile('url', data, config)
})
},
handleChange(file, filList) {
const isImg = this.imgTool.type.includes(file.raw.type)
const isLimit = file.size < this.imgTool.size
if (!isImg) {
this.$message.error('上传图片只能是“png”、“jpg”、“jpeg”格式!')
this.imgList = filList.filter(v => v.uid !== file.uid)
return
}
if (!isLimit) {
this.$message.error('上传图片大小不能超过 2MB!')
this.imgList = filList.filter(v => v.uid !== file.uid)
return
}
this.imgList.push(file)
},
hadnleRemove(_, fileList) {
this.imgList = fileList
},
fileReader(file) {
return new Promise(resolve => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = e => {
resolve(e.target.result)
}
})
}
}
}
</script>

上述案例是本地文件转 base64,如需在线图片转 base64,可以参考 用Vue来实现图片上传多种方式