vue实现上传插件
Vue 文件上传插件实现
文件上传是 Web 开发中常见的需求,Vue 生态系统中有多种实现方式。以下是几种主流方法:
原生 input 上传
使用 HTML5 的 input 元素配合 Vue 实现基础上传功能:
<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('/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
console.log('上传成功', response.data)
} catch (error) {
console.error('上传失败', error)
}
}
}
}
</script>
使用第三方插件
Vue 社区提供了多个成熟的上传组件:
- vue-upload-component
安装:
npm install vue-upload-component
<template>
<uploader :options="options" @complete="complete">
<uploader-unsupport></uploader-unsupport>
<uploader-drop>
<p>拖拽文件到此处上传</p>
<uploader-btn>选择文件</uploader-btn>
</uploader-drop>
<uploader-list></uploader-list>
</uploader>
</template>
<script>
import { Uploader, UploaderBtn, UploaderDrop, UploaderList, UploaderUnsupport } from 'vue-upload-component'
export default {
components: {
Uploader,
UploaderBtn,
UploaderDrop,
UploaderList,
UploaderUnsupport
},
data() {
return {
options: {
target: '/upload',
testChunks: false
}
}
},
methods: {
complete() {
console.log('上传完成')
}
}
}
</script>
- element-ui 上传组件 适用于使用 Element UI 的项目:
<template>
<el-upload
action="/upload"
:on-success="handleSuccess"
:before-upload="beforeUpload">
<el-button type="primary">点击上传</el-button>
</el-upload>
</template>
<script>
export default {
methods: {
beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('文件大小不能超过2MB')
}
return isLt2M
},
handleSuccess(response, file) {
this.$message.success('上传成功')
}
}
}
</script>
自定义上传组件
创建可复用的上传组件:
<template>
<div class="uploader">
<input
type="file"
ref="fileInput"
@change="handleFileChange"
style="display: none" />
<button @click="$refs.fileInput.click()">选择文件</button>
<div v-if="file" class="file-info">
{{ file.name }} ({{ formatFileSize(file.size) }})
<button @click="upload">上传</button>
</div>
<progress v-if="uploading" :value="progress" max="100"></progress>
</div>
</template>
<script>
export default {
data() {
return {
file: null,
uploading: false,
progress: 0
}
},
methods: {
handleFileChange(e) {
this.file = e.target.files[0]
},
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]
},
async upload() {
if (!this.file) return
this.uploading = true
const formData = new FormData()
formData.append('file', this.file)
try {
await axios.post('/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
this.progress = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
)
}
})
this.$emit('upload-success')
} catch (error) {
this.$emit('upload-error', error)
} finally {
this.uploading = false
}
}
}
}
</script>
高级功能实现
对于需要更复杂功能的场景:
分片上传
async uploadChunks(file) {
const chunkSize = 1 * 1024 * 1024 // 1MB
const chunks = Math.ceil(file.size / chunkSize)
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('chunkIndex', i)
formData.append('totalChunks', chunks)
formData.append('fileName', file.name)
await axios.post('/upload-chunk', formData)
}
await axios.post('/merge-chunks', {
fileName: file.name,
totalChunks: chunks
})
}
拖拽上传
<template>
<div
class="dropzone"
@dragover.prevent="dragover"
@dragleave.prevent="dragleave"
@drop.prevent="drop">
<p>拖拽文件到此处上传</p>
</div>
</template>
<script>
export default {
methods: {
dragover(event) {
event.currentTarget.classList.add('dragover')
},
dragleave(event) {
event.currentTarget.classList.remove('dragover')
},
drop(event) {
event.currentTarget.classList.remove('dragover')
const files = event.dataTransfer.files
if (files.length) {
this.handleFiles(files)
}
}
}
}
</script>
以上方案涵盖了从基础到高级的文件上传实现,可根据项目需求选择合适的方案。第三方插件提供更多开箱即用的功能,而自定义组件则提供更高的灵活性和控制权。







