Merge branch 'dev'

* dev:
  v1.7.3 rc.1
  chunk upload and multipart upload beta.2
  chunk upload and multipart upload beta.1
  multipart upload build
  multipart upload
  chunk upload
  chunk upload
This commit is contained in:
carodej
2020-07-30 08:58:19 +02:00
25 changed files with 633 additions and 334 deletions
@@ -238,6 +238,7 @@
flex: 0 0 100%;
@include transition(150ms);
position: relative;
scroll-behavior: smooth;
&.is-fileinfo-visible {
flex: 0 1 100%;
@@ -2,24 +2,39 @@
<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 v-if="isProcessingFile">
<refresh-cw-icon size="12" class="sync-alt"></refresh-cw-icon>
{{ $t('uploading.processing_file') }}
</span>
<span v-if="!isProcessingFile && uploadingFilesCount.total === 1">
{{ $t('uploading.progress_single_upload', {progress: uploadingFileProgress}) }}
</span>
<span v-if="!isProcessingFile && uploadingFilesCount.total > 1">
{{ $t('uploading.progress', {current:uploadingFilesCount.current, total: uploadingFilesCount.total, progress: uploadingFileProgress}) }}
</span>
</div>
<ProgressBar :progress="uploadingFileProgress"/>
<ProgressBar :progress="uploadingFileProgress" />
</div>
</transition>
</template>
<script>
import ProgressBar from '@/components/FilesView/ProgressBar'
import { RefreshCwIcon } from 'vue-feather-icons'
import {mapGetters} from 'vuex'
export default {
name: 'UploadProgress',
components: {
RefreshCwIcon,
ProgressBar,
},
computed: {
...mapGetters(['uploadingFileProgress', 'uploadingFilesCount'])
...mapGetters([
'uploadingFileProgress',
'uploadingFilesCount',
'isProcessingFile',
])
}
}
</script>
@@ -28,6 +43,24 @@
@import '@assets/vue-file-manager/_variables';
@import '@assets/vue-file-manager/_mixins';
.sync-alt {
animation: spin 1s linear infinite;
margin-right: 5px;
polyline, path {
stroke: $theme;
}
}
@keyframes spin {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
.info-panel-enter-active,
.info-panel-leave-active {
transition: all 0.3s ease;
@@ -52,6 +52,7 @@
border-radius: 6px;
width: 40px;
height: 40px;
object-fit: cover;
}
&.large {
+85 -115
View File
@@ -73,73 +73,101 @@ const Helpers = {
this.$store.dispatch('createFolder', folderName)
}
Vue.prototype.$uploadFiles = async function (files) {
// Prevent submit empty files
if (files && files.length == 0) return
Vue.prototype.$handleUploading = async function (files, parent_id) {
let fileCount = files ? files.length : 0
let fileCountSucceed = 1
let fileBuffer = []
// Append the file list to fileBuffer array
Array.prototype.push.apply(fileBuffer, files);
let fileSucceed = 0
// Update files count in progressbar
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileCountSucceed,
total: fileCount
current: fileSucceed,
total: files.length
})
// Reset upload progress to 0
store.commit('UPLOADING_FILE_PROGRESS', 0)
// Get parent id
const rootFolder = this.$store.getters.currentFolder
? this.$store.getters.currentFolder.unique_id
: 0
let parentFolder = this.$store.getters.currentFolder ? this.$store.getters.currentFolder.unique_id : 0
let rootFolder = parent_id ? parent_id : parentFolder
for (var i = files.length - 1; i >= 0; i--) {
let formData = new FormData()
// Upload files
do {
let file = fileBuffer.shift(),
chunks = []
// Append data
formData.append('file', files[i])
// Calculate ceils
let size = this.$store.getters.config.chunkSize,
chunksCeil = Math.ceil(file.size / size);
// Append form data
formData.append('parent_id', rootFolder)
// Create chunks
for (let i = 0; i < chunksCeil; i++) {
chunks.push(file.slice(
i * size, Math.min(i * size + size, file.size), file.type
));
}
// Upload data
await store.dispatch('uploadFiles', formData)
.then(() => {
// Progress file log
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileCountSucceed,
total: fileCount
// Set Data
let formData = new FormData(),
uploadedSize = 0,
isNotGeneralError = true,
filename = Array(16).fill(0).map(x => Math.random().toString(36).charAt(2)).join('') + '-' + file.name + '.part'
do {
let isLast = chunks.length === 1,
chunk = chunks.shift(),
attempts = 0
// Set form data
formData.set('file', chunk, filename);
formData.set('parent_id', rootFolder)
formData.set('is_last', isLast);
// Upload chunks
do {
await store.dispatch('uploadFiles', {
form: formData,
fileSize: file.size,
totalUploadedSize: uploadedSize
}).then(() => {
uploadedSize = uploadedSize + chunk.size
}).catch((error) => {
// Count attempts
attempts++
// Break uploading proccess
if (error.response.status === 500)
isNotGeneralError = false
// Show Error
if (attempts === 3)
this.$isSomethingWrong()
})
} while (isNotGeneralError && attempts !== 0 && attempts !== 3)
// 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:
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
break;
}
})
}
} while (isNotGeneralError && chunks.length !== 0)
fileSucceed++
// Progress file log
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileSucceed,
total: files.length
})
} while (fileBuffer.length !== 0)
store.commit('UPDATE_FILE_COUNT_PROGRESS', undefined)
}
Vue.prototype.$uploadFiles = async function (files) {
this.$handleUploading(files, undefined)
}
Vue.prototype.$uploadExternalFiles = async function (event, parent_id) {
@@ -148,67 +176,9 @@ const Helpers = {
if (event.dataTransfer.items.length == 0) return
// Get files
const files = [...event.dataTransfer.items].map(item => item.getAsFile());
let files = [...event.dataTransfer.items].map(item => item.getAsFile());
let fileCountSucceed = 1
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileCountSucceed,
total: files.length
})
for (var i = files.length - 1; i >= 0; i--) {
let formData = new FormData()
// Append data
formData.append('file', files[i])
// Append form data
formData.append('parent_id', parent_id)
// Upload data
await store.dispatch('uploadFiles', formData).then(() => {
// Progress file log
store.commit('UPDATE_FILE_COUNT_PROGRESS', {
current: fileCountSucceed,
total: files.length
})
// Progress file log
store.commit('INCREASE_FOLDER_ITEM', parent_id)
// Uploading finished
if (files.length === 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:
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
break;
}
})
}
this.$handleUploading(files, parent_id)
}
Vue.prototype.$downloadFile = function (url, filename) {
+3 -1
View File
@@ -680,7 +680,9 @@
"href": "Please confirm your payment."
},
"uploading": {
"progress": "上传文件 {current}/{total}"
"processing_file": "Processing File...",
"progress_single_upload": "上传文件 {progress}%",
"progress": "上传文件 {progress}% - {current}/{total}"
},
"user_add_card": {
"default_description": "",
+3 -1
View File
@@ -680,7 +680,9 @@
"href": "Please confirm your payment."
},
"uploading": {
"progress": "Uploading files {current}/{total}"
"processing_file": "Processing File...",
"progress_single_upload": "Uploading File {progress}%",
"progress": "Uploading File {progress}% - {current}/{total}"
},
"user_add_card": {
"default_description": "Your card will be charged for billing plans as first.",
+3 -1
View File
@@ -680,7 +680,9 @@
"href": "Prosím potvrďte Vašu platbu."
},
"uploading": {
"progress": "Nahrávam súbory {current}/{total}"
"processing_file": "Spracuvávam súbor...",
"progress_single_upload": "Nahrávam súbor {progress}%",
"progress": "Nahrávam súbory {progress}% - {current}/{total}"
},
"user_add_card": {
"default_description": "Vaša karta bude uložená a použitá pre platbu ako prvá.",
+5
View File
@@ -8,6 +8,7 @@ const defaultState = {
fileInfoDetail: undefined,
currentFolder: undefined,
uploadingFileProgress: 0,
isProcessingFile: false,
navigation: undefined,
isSearching: false,
browseHistory: [],
@@ -285,11 +286,15 @@ const mutations = {
STORE_CURRENT_FOLDER(state, folder) {
state.currentFolder = folder
},
PROCESSING_FILE(state, status) {
state.isProcessingFile = status
}
}
const getters = {
uploadingFileProgress: state => state.uploadingFileProgress,
uploadingFilesCount: state => state.uploadingFilesCount,
isProcessingFile: state => state.isProcessingFile,
fileInfoDetail: state => state.fileInfoDetail,
currentFolder: state => state.currentFolder,
browseHistory: state => state.browseHistory,
+39 -8
View File
@@ -42,6 +42,8 @@ const actions = {
.then(response => {
commit('ADD_NEW_FOLDER', response.data)
events.$emit('scrollTop')
if ( getters.currentFolder.location !== 'public' ) {
dispatch('getAppData')
}
@@ -72,7 +74,7 @@ const actions = {
})
.catch(() => isSomethingWrong())
},
uploadFiles: ({commit, getters}, files) => {
uploadFiles: ({commit, getters}, {form, fileSize, totalUploadedSize}) => {
return new Promise((resolve, reject) => {
// Get route
@@ -81,29 +83,58 @@ 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 => {
commit('UPLOADING_FILE_PROGRESS', percentCompleted)
var percentCompleted = Math.floor(((totalUploadedSize + event.loaded) / fileSize) * 100)
commit('UPLOADING_FILE_PROGRESS', percentCompleted >= 100 ? 100 : percentCompleted)
if (percentCompleted >= 100) {
commit('PROCESSING_FILE', true)
}
}
})
.then(response => {
commit('PROCESSING_FILE', false)
// Check if user is in uploading folder, if yes, than show new file
if (response.data.folder_id == getters.currentFolder.unique_id)
commit('ADD_NEW_ITEMS', response.data)
commit('UPLOADING_FILE_PROGRESS', 0)
resolve(response)
})
.catch(error => {
commit('PROCESSING_FILE', false)
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)
})
@@ -94,6 +94,10 @@
this.$refs.verifyPurchaseCode.setErrors({
'Purchase Code': ['Purchase code is invalid.']
});
} else if (error.response.status == 404) {
this.$refs.verifyPurchaseCode.setErrors({
'Purchase Code': ['You may have misconfigured the app, please read the readme file and try it again.']
});
} else {
this.$refs.verifyPurchaseCode.setErrors({
'Purchase Code': ['Something is wrong. Please try again.']