主题
上传进度
实现思路
- 使用
XMLHttpRequest或Fetch API进行文件上传。 - 监听上传过程中的进度事件。
- 计算上传百分比,并更新进度条。
代码示例
XHR
progress 事件对象属性:
lengthComputable:指示是否可以计算总字节数的布尔值,如:true。loaded:已上传的字节数。total:文件总字节数(如果可计算)。
计算进度:percentComplete = (loaded / total) * 100
js
const fileInput = document.getElementById('fileInput')
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0]
if (!file) return
const xhr = new XMLHttpRequest()
xhr.open('POST', '/upload-endpoint') // 替换为实际的上传端点
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percentComplete = (event.loaded / event.total) * 100 // 计算上传百分比
console.log(`Upload progress: ${percentComplete.toFixed(2)}%`)
}
})
xhr.onload = () => {
if (xhr.status === 200) {
console.log('上传完成', xhr.responseText)
} else {
console.error('上传失败', xhr.statusText)
}
}
const formData = new FormData()
formData.append('file', file)
xhr.send(formData)
})Fetch
原生 Fetch API 不支持上传进度监听。
Axios
由于 Axios 底层使用 XMLHttpRequest,因此支持上传进度监听。
js
const fileInput = document.getElementById('fileInput')
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0]
if (!file) return
const formData = new FormData()
formData.append('file', file)
axios
.post('/upload-endpoint', formData, {
onUploadProgress: (progressEvent) => {
const percentComplete = (progressEvent.loaded / progressEvent.total) * 100
console.log(`Upload progress: ${percentComplete.toFixed(2)}%`)
},
})
.then((response) => {
console.log('上传完成', response.data)
})
.catch((error) => {
console.error('上传失败', error)
})
})上传进度常见问题
为什么进度条卡在了 99% 不动了?
原因:progress 事件只反映上传进度,不包括服务器处理时间。
最佳实践:将进度条上传进度压缩为 0-90%,剩余 10% 用于服务器处理时间。
progress 事件频繁触发,影响性能怎么办?
可以考虑使用 throttle 降低事件触发频率,例如每 200ms 更新一次进度条。
js
import { throttle } from 'lodash'
const handleProgress = throttle((event) => {
if (event.lengthComputable) {
const percentComplete = (event.loaded / event.total) * 100
console.log(`Upload progress: ${percentComplete.toFixed(2)}%`)
}
}, 200)
xhr.upload.addEventListener('progress', handleProgress)