chunk upload

This commit is contained in:
carodej
2020-07-27 17:28:55 +02:00
parent 6f6115d5cb
commit 6ac543128e
11 changed files with 347 additions and 148 deletions
+74
View File
@@ -0,0 +1,74 @@
<script>
export default {
watch: {
chunks(n, o) {
if (n.length > 0) {
this.upload();
}
}
},
data() {
return {
file: null,
chunks: [],
uploaded: 0
};
},
computed: {
progress() {
return Math.floor((this.uploaded * 100) / this.file.size);
},
formData() {
let formData = new FormData;
formData.set('is_last', this.chunks.length === 1);
formData.set('file', this.chunks[0], `${this.file.name}.part`);
return formData;
},
config() {
return {
method: 'POST',
data: this.formData,
url: 'api/upload',
headers: {
'Content-Type': 'application/octet-stream'
},
onUploadProgress: event => {
this.uploaded += event.loaded;
}
};
}
},
methods: {
select(event) {
this.file = event.target.files.item(0);
this.createChunks();
},
upload() {
axios(this.config).then(response => {
this.chunks.shift();
}).catch(error => {});
},
createChunks() {
let size = 2048, chunks = Math.ceil(this.file.size / size);
for (let i = 0; i < chunks; i++) {
this.chunks.push(this.file.slice(
i * size, Math.min(i * size + size, this.file.size), this.file.type
));
}
}
}
}
</script>
<template>
<div>
<input type="file" @change="select">
<progress :value="progress"></progress>
</div>
</template>
@@ -2,7 +2,7 @@
<transition name="info-panel">
<div v-if="uploadingFilesCount" class="upload-progress">
<div class="progress-title">
<span>{{ $t('uploading.progress', {current:uploadingFilesCount.current, total: uploadingFilesCount.total}) }}</span>
<span>{{ $t('uploading.progress', {current:uploadingFilesCount.current, total: uploadingFilesCount.total, progress: uploadingFileProgress}) }}</span>
</div>
<ProgressBar :progress="uploadingFileProgress"/>
</div>
+58 -62
View File
@@ -85,60 +85,79 @@ const Helpers = {
total: fileCount
})
store.commit('UPLOADING_FILE_PROGRESS', 0)
// Get parent id
const rootFolder = this.$store.getters.currentFolder
? this.$store.getters.currentFolder.unique_id
: 0
for (var i = files.length - 1; i >= 0; i--) {
let file = files[i],
chunks = []
// Calculate ceils
let size = 1388608,
chunksCeil = Math.ceil(file.size / size);
// Create chunks
for (let i = 0; i < chunksCeil; i++) {
chunks.push(file.slice(
i * size, Math.min(i * size + size, file.size), file.type
));
}
// Set form Data
let formData = new FormData()
let uploadedSize = 0
// Append data
formData.append('file', files[i])
do {
let isLast = chunks.length === 1
let chunk = chunks.shift()
let attempts = 0
// Append form data
formData.append('parent_id', rootFolder)
// Set form data
formData.set('is_last', isLast);
formData.set('file', chunk, `${file.name}.part`);
formData.set('parent_id', rootFolder)
// Upload data
await store.dispatch('uploadFiles', formData)
.then(() => {
// Progress file log
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileCountSucceed,
total: fileCount
})
// Upload data
do {
await store.dispatch('uploadFiles', {
form: formData,
fileSize: file.size,
totalUploadedSize: uploadedSize
}).then(() => {
uploadedSize = uploadedSize + chunk.size
}).catch(() => {
// Uploading finished
if (fileCount === fileCountSucceed) {
store.commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
} else {
// Add uploaded file
fileCountSucceed++
}
}).catch(error => {
switch (error.response.status) {
case 423:
events.$emit('alert:open', {
emoji: '😬',
title: this.$t('popup_exceed_limit.title'),
message: this.$t('popup_exceed_limit.message')
})
break;
case 413:
events.$emit('alert:open', {
emoji: '😟',
title: this.$t('popup_paylod_error.title'),
message: this.$t('popup_paylod_error.message')
})
break;
default:
attempts++
if (attempts === 3) {
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
break;
}
})
}
})
} while (attempts !== 0 && attempts !== 3)
} while (chunks.length !== 0)
// Progress file log
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileCountSucceed,
total: fileCount
})
// Uploading finished
if (fileCount === fileCountSucceed) {
store.commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
} else {
// Add uploaded file
fileCountSucceed++
}
}
}
@@ -184,29 +203,6 @@ const Helpers = {
// Add uploaded file
fileCountSucceed++
}
}).catch(error => {
switch (error.response.status) {
case 423:
events.$emit('alert:open', {
emoji: '😬',
title: this.$t('popup_exceed_limit.title'),
message: this.$t('popup_exceed_limit.message')
})
break;
case 413:
events.$emit('alert:open', {
emoji: '😟',
title: this.$t('popup_paylod_error.title'),
message: this.$t('popup_paylod_error.message')
})
break;
default:
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
break;
}
})
}
}
+1 -1
View File
@@ -680,7 +680,7 @@
"href": "Please confirm your payment."
},
"uploading": {
"progress": "Uploading files {current}/{total}"
"progress": "Uploading File {progress}% - {current}/{total}"
},
"user_add_card": {
"default_description": "Your card will be charged for billing plans as first.",
+31 -7
View File
@@ -72,7 +72,7 @@ const actions = {
})
.catch(() => isSomethingWrong())
},
uploadFiles: ({commit, getters}, files) => {
uploadFiles: ({commit, getters}, {form, fileSize, totalUploadedSize}) => {
return new Promise((resolve, reject) => {
// Get route
@@ -81,12 +81,15 @@ const actions = {
: '/api/upload'
axios
.post(route, files, {
.post(route, form, {
headers: {
'Content-Type': 'multipart/form-data'
'Content-Type': 'application/octet-stream'
},
onUploadProgress: progressEvent => {
var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
onUploadProgress: event => {
let loaded = totalUploadedSize + event.loaded
var percentCompleted = Math.floor((loaded * 100) / fileSize)
commit('UPLOADING_FILE_PROGRESS', percentCompleted)
}
@@ -97,13 +100,34 @@ const actions = {
if (response.data.folder_id == getters.currentFolder.unique_id)
commit('ADD_NEW_ITEMS', response.data)
commit('UPLOADING_FILE_PROGRESS', 0)
resolve(response)
})
.catch(error => {
reject(error)
switch (error.response.status) {
case 423:
events.$emit('alert:open', {
emoji: '😬',
title: i18n.t('popup_exceed_limit.title'),
message: i18n.t('popup_exceed_limit.message')
})
break;
case 413:
events.$emit('alert:open', {
emoji: '😟',
title: i18n.t('popup_paylod_error.title'),
message: i18n.t('popup_paylod_error.message')
})
break;
default:
events.$emit('alert:open', {
title: i18n.t('popup_error.title'),
message: i18n.t('popup_error.message'),
})
break;
}
// Reset uploader
commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
})