个人谈谈upload 组件
最简单的头像上传功能,直接使用 :action 上传即可
但是涉及到需要携带其他的数据时, 需要使用formdata 数据格式
1. 直接上传file 文件让后端进行操作
2. 前端将图片 转为base64 编码。 后端对base64 进行操作
个人理解 通过action 上传, 后端返回图片在线地址或者base64 编码。 前端展示
<el-form-item label="头像">
<el-upload class="avatar-uploader"
:action="Action"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl"
:src="imageUrl"
class="avatar">
<i v-else
class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
Action: 'http://localhost:9562/admin/upload'
handleAvatarSuccess(res, file) {
// this.imageUrl = URL.createObjectURL(file.raw)
console.log(res)
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isJPG && isLt2M
},
个人理解 自定义upload -- 此时的图片上传需要使用 formdata 数据格式( var formdata = new FormData()
formdata.append('file', file)),
我的后端node +koa ctx.request.file.file 接收到文件
<template>
<div class="upload-container">
<el-upload
class="avatar-uploader"
ref="upload"
action="#"
accept="image/jpeg,image/png,image/jpg"
list-type="picture"
:before-upload="beforeUpdate"
:http-request="handleAvatarSuccess"
>
<img v-if="imgBase64" :src="imgBase64" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</template>
<script>
export default {
name: 'SingleImageUpload',
props: {
value: {
type: String,
default: ''
}
},
data() {
return {
imgInfo: '',
imgBase64: ''
}
},
computed: {
imageUrl() {
return this.value
}
},
methods: {
photoCompress(file, compressedOption, callback) {
let fileReader = new FileReader()
fileReader.readAsDataURL(file)
fileReader.onload = () => {
let fileResult = fileReader.result
this.canvasDataURL(fileResult, compressedOption, callback)
}
},
// 图片渲染至画布 并获取指定质量图片
canvasDataURL(path, compressedOption, callback) {
let img = new Image()
img.src = path
img.onload = () => {
// 设置压缩后图片规格
let quality = compressedOption.quality
let w = compressedOption.width || img.width
// 判断只存在宽度时,根据比例设置高度
let h =
compressedOption.height ||
(compressedOption.width
? compressedOption.width / (img.width / img.height)
: '') ||
img.height
// 生成canvas
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
// 设置宽高并渲染图片
canvas.width = w
canvas.height = h
ctx.drawImage(img, 0, 0, w, h)
let base64 = canvas.toDataURL('image/jpeg', quality)
// 回调函数返回base64的值
callback(base64)
}
},
convertBase64UrlToFile(urlData, filename) {
let arr = urlData.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
},
// 图片上传
beforeUpdate(file, fileList) {
console.log('file', file)
return new Promise((resolve, reject) => {
// 这个压缩函数,就是上面我们写的
this.photoCompress(
file,
{
quality: 0.2
// width: 0,
// height: 0
},
(base64Codes) => {
this.imgBase64 = base64Codes
let newFile = this.convertBase64UrlToFile(base64Codes, file.name)
此处为新File
console.log('newFile', newFile)
resolve(newFile)
}
)
})
},
handleAvatarSuccess(){
自定义上传方法
upload().then
},
fileChange(file) {
this.$refs.upload.clearFiles() //清除文件对象
this.imgInfo = file
}
}
}
</script>
不实用axios 模式
var xhr = new XMLHttpRequest()
xhr.open('PUT', this.ossUrl)
xhr.send(this.imgBase64)
xhr.onload = function() {
console.log('执行了', xhr)
// 请求结束后,在此处编写处理代码。
}
读取二进制文件流
UploadImage(file) {
this.imgFile = file.file
let reader = new FileReader()
reader.readAsArrayBuffer(file.file)
var that = this
reader.onloadend = function(e) {
that.imgBase64 = e.target.result
}
},