vue实现压缩上传文件
压缩上传文件的实现方法
使用HTML5的File API和Canvas进行压缩
前端可以使用HTML5的File API读取文件,对于图片文件可以利用Canvas进行压缩。通过Canvas的drawImage和toDataURL方法调整图片质量,实现压缩效果。
function compressImage(file, quality = 0.8) {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onload = (event) => {
const img = new Image()
img.onload = () => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
canvas.toBlob((blob) => {
resolve(new File([blob], file.name, { type: 'image/jpeg' }))
}, 'image/jpeg', quality)
}
img.src = event.target.result
}
reader.readAsDataURL(file)
})
}
使用第三方库进行更高效的压缩
对于更复杂的压缩需求,可以使用compressorjs等专业压缩库。这些库提供了更多压缩选项和更好的兼容性。

import Compressor from 'compressorjs'
function compressWithLibrary(file) {
return new Promise((resolve) => {
new Compressor(file, {
quality: 0.6,
success(result) {
resolve(result)
},
error(err) {
console.error(err.message)
resolve(file) // 压缩失败返回原文件
}
})
})
}
文件上传实现
压缩后的文件可以通过axios或其他HTTP库上传到服务器。创建FormData对象并附加压缩后的文件。

async function uploadFile(file) {
const compressedFile = await compressImage(file)
const formData = new FormData()
formData.append('file', compressedFile)
try {
const response = await axios.post('/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
})
console.log('上传成功', response.data)
} catch (error) {
console.error('上传失败', error)
}
}
进度显示和限制文件大小
上传过程中可以显示进度条,并在压缩前检查文件大小,避免不必要的压缩操作。
function checkFileSize(file, maxSizeMB = 5) {
const maxSizeBytes = maxSizeMB * 1024 * 1024
return file.size <= maxSizeBytes
}
// 上传带进度显示
function uploadWithProgress(file, onProgress) {
const config = {
onUploadProgress: (progressEvent) => {
const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total)
onProgress(percent)
}
}
return axios.post('/upload', file, config)
}
完整组件示例
在Vue组件中整合上述功能,提供完整的文件选择和上传体验。
<template>
<div>
<input type="file" @change="handleFileChange" />
<button @click="upload" :disabled="!file">上传</button>
<progress v-if="progress >= 0" :value="progress" max="100"></progress>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
file: null,
progress: -1
}
},
methods: {
async handleFileChange(event) {
this.file = event.target.files[0]
},
async upload() {
if (!this.file) return
const compressedFile = await this.compressImage(this.file)
const formData = new FormData()
formData.append('file', compressedFile)
try {
await axios.post('/upload', formData, {
onUploadProgress: (progressEvent) => {
this.progress = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
)
}
})
this.$emit('upload-success')
} catch (error) {
console.error('上传失败', error)
} finally {
this.progress = -1
}
},
compressImage(file) {
// 实现压缩逻辑
}
}
}
</script>






