console
function splitBlob(blob, chunkSize) {
if (!chunkSize|| blob.size <= chunkSize) return [blob]
const chunkList = []
const filesize = blob.size
let start = 0
let end = 0
while (start < filesize) {
end = start + chunkSize
if (end > filesize) end = filesize
const chunk = blob.slice(start, end)
chunkList.push(chunk)
start = end
}
return chunkList
}
async function blobSplitHandle ({ blob, chunkSize, chunkHandle, onProgress }) {
const taskList = splitBlob(blob, chunkSize).map((chunk, index) => {
return {
index,
chunk,
chunkRate: chunk.size / blob.size,
loaded: 0,
total: 0,
scheduleRate: 0
}
})
function updateProgress () {
const scheduleRate = taskList.reduce((value, task) => {
if (task.scheduleRate) return (value + (task.chunkRate * task.scheduleRate))
return value
}, 0)
onProgress && onProgress({
loaded: parseInt(blob.size * scheduleRate),
total: blob.size
})
}
function handleUploadProgress (task, event) {
const { loaded, total } = event
task.loaded = loaded
task.total = total
task.scheduleRate = loaded / total
updateProgress()
}
let result = undefined
for (const task of taskList) {
result = await Promise.resolve(chunkHandle(task.chunk, task.index, handleUploadProgress.bind(task, task)), result)
handleUploadProgress(task, task)
}
onProgress && onProgress({
loaded: blob.size,
total: blob.size
})
}
<form>
<div class="form-group">
<label for="exampleFormControlFile1">选择文件</label>
<input type="file" class="form-control-file" id="file" onChange="upload()">
<div class="progress">
<div class="progress-bar progress-bar-striped" style="width: 0%"></div>
</div>
</div>
</form>
<script type="text/javascript">
function upload() {
const blob = document.getElementById('file').files[0]
function chunkHandle (chunk, index, handleProgress) {
const formData = new FormData()
formData.append('file', chunk, `${blob.name}_chunk${index}`)
return axios.post('https://jsonplaceholder.typicode.com/posts/', formData, {
onUploadProgress: handleProgress
})
}
function onProgress (event) {
const { loaded, total } = event
const schedule = Number(loaded / total * 100).toFixed(2)
document.querySelector('.progress-bar').style.width = `${schedule}%`
console.log(loaded, total, schedule)
}
blobSplitHandle({
blob: blob,
chunkSize: 5 * 1024 * 1024,
chunkHandle: chunkHandle,
onProgress: onProgress
}).then(() => {
console.log('上传完成')
}, (error) => {
console.error(error)
console.log('上传失败')
})
}
</script>