vue实现上传
文件上传基础实现
使用Vue配合HTML5的<input type="file">元素实现基础上传功能:
<template>
<div>
<input type="file" @change="handleFileUpload"/>
<button @click="submitFile">上传</button>
</div>
</template>
<script>
export default {
data() {
return {
file: null
}
},
methods: {
handleFileUpload(event) {
this.file = event.target.files[0]
},
async submitFile() {
const formData = new FormData()
formData.append('file', this.file)
try {
const response = await axios.post('/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
console.log('上传成功', response.data)
} catch (error) {
console.error('上传失败', error)
}
}
}
}
</script>
多文件上传支持
通过添加multiple属性实现多文件选择:
<input type="file" multiple @change="handleMultiUpload"/>
对应处理方法:
handleMultiUpload(event) {
this.files = Array.from(event.target.files)
},
async submitFiles() {
const formData = new FormData()
this.files.forEach(file => {
formData.append('files[]', file)
})
// 其余上传逻辑与单文件相同
}
文件预览与验证
在上传前进行文件类型和大小验证:
validateFile(file) {
const validTypes = ['image/jpeg', 'image/png']
const maxSize = 5 * 1024 * 1024 // 5MB
if (!validTypes.includes(file.type)) {
alert('仅支持JPEG/PNG格式')
return false
}
if (file.size > maxSize) {
alert('文件大小超过限制')
return false
}
return true
}
实现图片预览功能:
<template>
<div v-if="previewUrl">
<img :src="previewUrl" width="200"/>
</div>
</template>
<script>
methods: {
handleFileUpload(event) {
const file = event.target.files[0]
if (!this.validateFile(file)) return
this.file = file
this.previewUrl = URL.createObjectURL(file)
}
}
</script>
进度显示实现
使用axios的onUploadProgress回调显示上传进度:

async submitFile() {
const config = {
headers: {'Content-Type': 'multipart/form-data'},
onUploadProgress: progressEvent => {
const percent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
)
this.uploadProgress = percent
}
}
await axios.post('/api/upload', formData, config)
}
模板中添加进度显示:
<progress :value="uploadProgress" max="100"></progress>
<span>{{ uploadProgress }}%</span>
第三方组件集成
使用vue-dropzone组件实现拖拽上传:
npm install vue2-dropzone
组件使用示例:

import vue2Dropzone from 'vue2-dropzone'
import 'vue2-dropzone/dist/vue2Dropzone.min.css'
export default {
components: {
vueDropzone: vue2Dropzone
},
data() {
return {
dropzoneOptions: {
url: '/api/upload',
thumbnailWidth: 150,
maxFilesize: 5,
acceptedFiles: 'image/*',
addRemoveLinks: true
}
}
}
}
模板中使用:
<vue-dropzone
id="dropzone"
:options="dropzoneOptions"
@vdropzone-success="uploadSuccess"
></vue-dropzone>
大文件分片上传
实现大文件分片上传逻辑:
async chunkedUpload(file) {
const chunkSize = 2 * 1024 * 1024 // 2MB
const chunks = Math.ceil(file.size / chunkSize)
const fileMd5 = await this.calculateFileMD5(file)
for (let i = 0; i < chunks; i++) {
const start = i * chunkSize
const end = Math.min(start + chunkSize, file.size)
const chunk = file.slice(start, end)
const formData = new FormData()
formData.append('file', chunk)
formData.append('chunkNumber', i)
formData.append('totalChunks', chunks)
formData.append('identifier', fileMd5)
await axios.post('/api/chunk-upload', formData)
}
// 通知服务器合并分片
await axios.post('/api/merge-chunks', {
filename: file.name,
identifier: fileMd5,
totalChunks: chunks
})
}
服务器端注意事项
Node.js Express处理文件上传示例:
const multer = require('multer')
const upload = multer({ dest: 'uploads/' })
app.post('/api/upload', upload.single('file'), (req, res) => {
console.log(req.file)
res.json({ message: '上传成功' })
})
对于分片上传需要额外处理:
app.post('/api/chunk-upload', upload.single('file'), (req, res) => {
const { chunkNumber, totalChunks, identifier } = req.body
// 存储分片到临时目录
const chunkPath = `temp/${identifier}-${chunkNumber}`
fs.renameSync(req.file.path, chunkPath)
res.json({ received: true })
})






