vue 实现视频上传
视频上传功能实现
在Vue中实现视频上传功能需要结合前端和后端的协作。以下是详细的实现方法:
前端实现
创建文件上传组件,使用<input type="file">元素:
<template>
<div>
<input type="file" accept="video/*" @change="handleFileUpload" />
<button @click="uploadVideo">上传视频</button>
<div v-if="progress > 0">上传进度: {{progress}}%</div>
</div>
</template>
处理文件选择和上传逻辑:
<script>
export default {
data() {
return {
selectedFile: null,
progress: 0
}
},
methods: {
handleFileUpload(event) {
this.selectedFile = event.target.files[0]
},
async uploadVideo() {
if (!this.selectedFile) return
const formData = new FormData()
formData.append('video', this.selectedFile)
try {
const response = await axios.post('/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
this.progress = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
)
}
})
console.log('上传成功', response.data)
} catch (error) {
console.error('上传失败', error)
}
}
}
}
</script>
后端API实现
Node.js Express示例:
const express = require('express')
const multer = require('multer')
const path = require('path')
const app = express()
const upload = multer({
dest: 'uploads/',
limits: {
fileSize: 100 * 1024 * 1024 // 限制100MB
}
})
app.post('/api/upload', upload.single('video'), (req, res) => {
if (!req.file) {
return res.status(400).send('没有上传文件')
}
// 这里可以添加文件验证逻辑
const allowedTypes = ['video/mp4', 'video/webm']
if (!allowedTypes.includes(req.file.mimetype)) {
return res.status(400).send('不支持的文件类型')
}
res.json({
message: '文件上传成功',
filename: req.file.filename,
path: req.file.path
})
})
app.listen(3000, () => console.log('服务器启动'))
文件验证和限制
前端验证文件类型和大小:
handleFileUpload(event) {
const file = event.target.files[0]
const maxSize = 100 * 1024 * 1024 // 100MB
if (!file.type.includes('video/')) {
alert('请选择视频文件')
return
}
if (file.size > maxSize) {
alert('文件太大,最大支持100MB')
return
}
this.selectedFile = file
}
进度显示优化
使用进度条组件增强用户体验:
<progress :value="progress" max="100"></progress>
<span v-if="progress > 0 && progress < 100">{{progress}}%</span>
<span v-else-if="progress === 100">上传完成!</span>
断点续传实现
对于大文件上传,实现分片上传:
async uploadLargeVideo() {
const chunkSize = 5 * 1024 * 1024 // 5MB每片
const chunks = Math.ceil(this.selectedFile.size / chunkSize)
for (let i = 0; i < chunks; i++) {
const start = i * chunkSize
const end = Math.min(start + chunkSize, this.selectedFile.size)
const chunk = this.selectedFile.slice(start, end)
const formData = new FormData()
formData.append('chunk', chunk)
formData.append('chunkIndex', i)
formData.append('totalChunks', chunks)
formData.append('filename', this.selectedFile.name)
await axios.post('/api/upload-chunk', formData, {
headers: {'Content-Type': 'multipart/form-data'}
})
this.progress = Math.round(((i + 1) / chunks) * 100)
}
await axios.post('/api/merge-chunks', {
filename: this.selectedFile.name,
totalChunks: chunks
})
}
视频预览功能
上传前预览视频:
<video v-if="videoUrl" :src="videoUrl" controls width="300"></video>
handleFileUpload(event) {
const file = event.target.files[0]
this.selectedFile = file
this.videoUrl = URL.createObjectURL(file)
}
错误处理和重试机制
添加错误处理和自动重试:
async uploadWithRetry(formData, retries = 3) {
try {
return await axios.post('/api/upload', formData, {
headers: {'Content-Type': 'multipart/form-data'}
})
} catch (error) {
if (retries > 0) {
return this.uploadWithRetry(formData, retries - 1)
}
throw error
}
}
文件大小转换
格式化显示文件大小:
formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes'
const k = 1024
const sizes = ['Bytes', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
上传限制提示
显示上传限制信息:
<p>支持格式: MP4, WebM</p>
<p>最大文件大小: {{formatFileSize(100 * 1024 * 1024)}}</p>
这些方法提供了完整的视频上传解决方案,可以根据实际需求进行调整和扩展。







