Vue 图片上传实现方法
基础实现(使用原生 input 和 FileReader)
<template>
<div>
<input type="file" @change="handleFileChange" accept="image/*">
<img v-if="imageUrl" :src="imageUrl" alt="Preview" style="max-width: 300px;">
</div>
</template>
<script>
export default {
data() {
return {
imageUrl: ''
}
},
methods: {
handleFileChange(e) {
const file = e.target.files[0]
if (!file) return
const reader = new FileReader()
reader.onload = (e) => {
this.imageUrl = e.target.result
}
reader.readAsDataURL(file)
}
}
}
</script>
使用第三方库(如 axios 上传到服务器)
<template>
<div>
<input type="file" ref="fileInput" @change="handleFileUpload">
<button @click="uploadFile">上传</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
selectedFile: null
}
},
methods: {
handleFileUpload() {
this.selectedFile = this.$refs.fileInput.files[0]
},
uploadFile() {
if (!this.selectedFile) return
const formData = new FormData()
formData.append('file', this.selectedFile)
axios.post('/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(response => {
console.log('上传成功', response.data)
}).catch(error => {
console.error('上传失败', error)
})
}
}
}
</script>
使用 Element UI 组件库
<template>
<el-upload
action="/api/upload"
:on-success="handleSuccess"
:before-upload="beforeUpload">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</template>
<script>
export default {
methods: {
beforeUpload(file) {
const isImage = file.type.includes('image/')
const isLt2M = file.size / 1024 / 1024 < 2
if (!isImage) {
this.$message.error('只能上传图片文件')
}
if (!isLt2M) {
this.$message.error('图片大小不能超过 2MB')
}
return isImage && isLt2M
},
handleSuccess(response, file) {
this.$message.success('上传成功')
console.log('文件地址:', response.url)
}
}
}
</script>
图片压缩处理
compressImage(file, quality = 0.8) {
return new Promise((resolve) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = (event) => {
const img = new Image()
img.src = event.target.result
img.onload = () => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
const maxWidth = 1024
const maxHeight = 1024
let width = img.width
let height = img.height
if (width > maxWidth || height > maxHeight) {
const ratio = Math.min(maxWidth / width, maxHeight / height)
width *= ratio
height *= ratio
}
canvas.width = width
canvas.height = height
ctx.drawImage(img, 0, 0, width, height)
canvas.toBlob(
(blob) => resolve(new File([blob], file.name, { type: 'image/jpeg' })),
'image/jpeg',
quality
)
}
}
})
}
多文件上传实现
<template>
<div>
<input type="file" multiple @change="handleMultipleFiles">
<button @click="uploadMultiple">上传多个文件</button>
</div>
</template>
<script>
export default {
data() {
return {
files: []
}
},
methods: {
handleMultipleFiles(e) {
this.files = Array.from(e.target.files)
},
async uploadMultiple() {
if (this.files.length === 0) return
const formData = new FormData()
this.files.forEach(file => {
formData.append('files[]', file)
})
try {
const response = await axios.post('/api/upload-multiple', formData)
console.log('上传成功', response.data)
} catch (error) {
console.error('上传失败', error)
}
}
}
}
</script>
