Web: Files: Re-written uploading process to async controlled chain calls

This commit is contained in:
Alexey Safronov 2020-12-09 13:54:04 +03:00
parent 254b03032f
commit bd18aa1415

View File

@ -702,20 +702,24 @@ export const startUpload = (uploadFiles, folderId, t) => {
console.log("start upload", state.files.uploadData);
let newFiles = state.files.uploadData.files;
let filesSize = 0;
const convertFiles = [];
let convertFilesSize = 0;
let uploadStatus = null;
for (let index of Object.keys(uploadFiles)) {
const item = uploadFiles[index];
if (item.size !== 0) {
const parts = item.name.split(".");
const ext = parts.length > 1 ? "." + parts.pop() : "";
if (canConvert(ext)(state)) {
convertFiles.push({ file: item, toFolderId: folderId });
convertFilesSize += item.size;
} else {
newFiles.push({ file: item, toFolderId: folderId });
filesSize += item.size;
const needConvert = canConvert(ext)(state);
newFiles.push({
file: item,
toFolderId: folderId,
action: needConvert ? "convert" : "upload",
error: null,
});
filesSize += item.size;
if (needConvert) {
uploadStatus = "pending";
}
} else {
dispatch(
@ -729,16 +733,13 @@ export const startUpload = (uploadFiles, folderId, t) => {
}
}
const uploadStatus = convertFiles.length ? "pending" : null;
const showConvertDialog = !!convertFiles.length;
//const showConvertDialog = uploadStatus === "pending";
const percent = state.files.uploadData.percent;
const uploadedFiles = state.files.uploadData.uploadedFiles;
console.log("newFiles: ", newFiles);
const newUploadData = {
files: newFiles,
filesSize,
convertFiles,
convertFilesSize,
uploadStatus,
uploadedFiles,
percent,
@ -746,80 +747,96 @@ export const startUpload = (uploadFiles, folderId, t) => {
};
dispatch(setUploadData(newUploadData));
if (showConvertDialog) {
dispatch(setConvertDialogVisible(showConvertDialog));
}
// if (showConvertDialog) {
// dispatch(setConvertDialogVisible(showConvertDialog));
// }
if (state.files.uploadData.uploaded)
startUploadFiles(
t,
newFiles.length,
convertFiles.length,
dispatch,
getState
);
startUploadFiles(t, newFiles.length, dispatch, getState);
};
};
const startUploadFiles = (
t,
filesLength,
convertFilesLength,
dispatch,
getState
) => {
if (filesLength > 0 || convertFilesLength > 0) {
const state = getState();
const percent = state.files.uploadData.percent;
const startUploadFiles = async (t, filesLength, dispatch, getState) => {
if (filesLength === 0) return;
const progressData = {
visible: true,
percent,
label: "",
icon: "upload",
alert: false,
};
progressData.label = t("UploadingLabel", {
file: 0,
totalFiles: filesLength + convertFilesLength,
});
dispatch(setPrimaryProgressBarData(progressData));
startSessionFunc(0, t, dispatch, getState);
let state = getState();
const percent = state.files.uploadData.percent;
const progressData = {
visible: true,
percent,
label: "",
icon: "upload",
alert: false,
};
progressData.label = t("UploadingLabel", {
file: 0,
totalFiles: filesLength,
});
dispatch(setPrimaryProgressBarData(progressData));
for (let index = 0; index < filesLength; index++) {
await startSessionFunc(index, t, dispatch, getState);
}
//TODO: startConvertFunc
//TODO: All files has been uploaded
state = getState();
const { files } = state.files.uploadData;
const totalErrorsCount = sumBy(files, (f) => (f.error ? 1 : 0));
if (totalErrorsCount > 0) return;
const uploadData = {
files: [],
filesSize: 0,
uploadStatus: null,
uploadedFiles: 0,
percent: 0,
uploaded: true,
};
setTimeout(() => {
dispatch(clearPrimaryProgressData());
dispatch(setUploadData(uploadData));
}, TIMEOUT);
};
const chunkSize = 1024 * 1023; //~0.999mb
const throttleRefreshFiles = throttle((toFolderId, dispatch, getState) => {
refreshFiles(toFolderId, dispatch, getState);
return refreshFiles(toFolderId, dispatch, getState).catch((err) => {
console.log("RefreshFiles failed", err);
return Promise.resolve();
});
}, 10000);
const startSessionFunc = (indexOfFile, t, dispatch, getState) => {
const state = getState();
const { uploadData } = state.files;
const { uploaded, files, convertFiles } = uploadData;
const { uploaded, files } = uploadData;
const currentFiles = uploaded ? convertFiles : files;
console.log("START UPLOAD SESSION FUNC", uploadData);
if (!uploaded && files.length === 0) {
uploadData.uploaded = true;
dispatch(setUploadData(uploadData));
return;
}
let item = files[indexOfFile] || { file: null, toFolderId: null };
let { file, toFolderId } = item;
//let isLatestFile = indexOfFile === files.length - 1;
const item = files[indexOfFile];
if (uploaded) {
if (convertFiles.length) {
let item = convertFiles[indexOfFile] || { file: null, toFolderId: null };
file = item.file;
toFolderId = item.toFolderId;
//isLatestFile = indexOfFile === convertFiles.length - 1;
} else {
//Test return empty convert files
return;
}
if (!item) {
console.error("Empty files");
debugger;
return Promise.resolve();
}
const { file, toFolderId /*, action*/ } = item;
const fileName = file.name;
const fileSize = file.size;
const relativePath = file.path
@ -828,15 +845,15 @@ const startSessionFunc = (indexOfFile, t, dispatch, getState) => {
? file.webkitRelativePath.slice(0, -file.name.length)
: "";
let location;
const requestsDataArray = [];
const chunks = Math.ceil(file.size / chunkSize, chunkSize);
let chunk = 0;
api.files
return api.files
.startUploadSession(toFolderId, fileName, fileSize, relativePath)
.then((res) => {
location = res.data.location;
const location = res.data.location;
const requestsDataArray = [];
const chunks = Math.ceil(file.size / chunkSize, chunkSize);
let chunk = 0;
while (chunk < chunks) {
const offset = chunk * chunkSize;
const formData = new FormData();
@ -844,19 +861,248 @@ const startSessionFunc = (indexOfFile, t, dispatch, getState) => {
requestsDataArray.push(formData);
chunk++;
}
return { location, requestsDataArray, fileSize };
})
.then(() => {
throttleRefreshFiles(toFolderId, dispatch, getState);
//TODO: rewrite to async function
sendChunk(
currentFiles,
.then(({ location, requestsDataArray, fileSize }) =>
uploadFileChunks(
location,
requestsDataArray,
fileSize,
indexOfFile,
t,
dispatch,
t,
getState
)
)
.catch((err) => {
console.error(err);
const state = getState();
const { uploadData } = state.files;
uploadData.files[indexOfFile].error = err;
dispatch(setUploadData(uploadData));
const newPercent = getNewPercent(fileSize, indexOfFile, getState);
dispatch(
setPrimaryProgressBarData({
icon: "upload",
label: "Error", //TODO: Add translation
percent: newPercent,
visible: true,
alert: true,
})
);
return Promise.resolve();
});
};
// const sendChunk = (
// files,
// location,
// requestsDataArray,
// indexOfFile,
// t,
// dispatch,
// getState
// ) => {
// const state = getState();
// const { uploadData } = state.files;
// const { uploaded, percent, uploadedFiles } = uploadData;
// let newPercent = percent;
// const file =
// uploadData.files[indexOfFile] || uploadData.convertFiles[indexOfFile];
// const toFolderId = file.toFolderId;
// return;
// //sendRequestFunc(0);
// };
const uploadFileChunks = async (
location,
requestsDataArray,
fileSize,
indexOfFile,
dispatch,
t,
getState
) => {
const length = requestsDataArray.length;
for (let index = 0; index < length; index++) {
const res = await api.files.uploadFile(location, requestsDataArray[index]);
console.log(`Uploaded chunk ${index}/${length}`, res);
//let isLatestFile = indexOfFile === newFilesLength - 1;
const uploadedSize =
res && res.data && res.data.data && res.data.data.uploaded
? fileSize
: index * chunkSize;
const newPercent = getNewPercent(uploadedSize, indexOfFile, getState);
const newState = getState();
const { uploadedFiles, files } = newState.files.uploadData;
dispatch(
setPrimaryProgressBarData({
icon: "upload",
label: t("UploadingLabel", {
file: uploadedFiles,
totalFiles: files.length,
}),
percent: newPercent,
visible: true,
})
);
}
// All chuncks are uploaded
const newState = getState();
const { files } = newState.files.uploadData;
const currentFile = files[indexOfFile];
if (!currentFile) return Promise.resolve();
const { toFolderId } = currentFile;
return throttleRefreshFiles(toFolderId, dispatch, getState);
};
const getNewPercent = (uploadedSize, indexOfFile, getState) => {
const newState = getState();
const { files } = newState.files.uploadData;
const newTotalSize = sumBy(files, (f) => f.file.size);
const totalUploadedFiles = files.filter((_, i) => i < indexOfFile);
const totalUploadedSize = sumBy(totalUploadedFiles, (f) => f.file.size);
const newPercent = ((uploadedSize + totalUploadedSize) / newTotalSize) * 100;
console.log(
`newPercent=${newPercent} (newTotalSize=${newTotalSize} totalUploadedSize=${totalUploadedSize} indexOfFile=${indexOfFile})`
);
return newPercent;
};
/*const sendRequestFunc = (index) => {
api.files
.uploadFile(location, requestsDataArray[index])
.then((res) => {
//percent problem? use getState()
const newState = getState();
const newFilesLength = newState.files.uploadData.files.length;
const newTotalSize = sumBy(
newState.files.uploadData.files,
(f) => f.file.size
);
//console.log("newTotalSize ", newTotalSize);
let isLatestFile = indexOfFile === newFilesLength - 1;
const fileId = res.data.data.id;
const totalUploadedFiles = newState.files.uploadData.files.filter(
(_, i) => i < indexOfFile
);
//console.log("indexOfFile ", indexOfFile);
//console.log("totalUploadedFiles ", totalUploadedFiles);
const totalUploadedSize = sumBy(totalUploadedFiles, (f) => f.file.size);
//console.log("totalUploadedSize ", totalUploadedSize);
if (index < requestsDataArray.length) {
//newPercent = (index / requestsDataArray.length) * 100;
newPercent =
((index * chunkSize + totalUploadedSize) / newTotalSize) * 100;
}
//if (res.data.data && res.data.data.uploaded) {
// newPercent = (currentFile.size / newTotalSize) * 100;
//}
//console.log("newPercent", newPercent);
if (index + 1 !== requestsDataArray.length) {
dispatch(
setPrimaryProgressBarData({
icon: "upload",
label: t("UploadingLabel", {
file: uploadedFiles,
totalFiles: files.length,
}),
percent: newPercent,
visible: true,
alert: false,
})
);
sendRequestFunc(index + 1);
} else if (uploaded) {
api.files.convertFile(fileId).then((convertRes) => {
if (convertRes && convertRes[0] && convertRes[0].progress !== 100) {
uploadData.percent = newPercent;
getConvertProgress(
fileId,
t,
uploadData,
isLatestFile,
indexOfFile,
dispatch,
getState
);
}
});
} else if (isLatestFile) {
if (uploaded) {
updateFiles(toFolderId, dispatch, getState);
} else {
const uploadStatus = getState().files.uploadData.uploadStatus;
if (uploadStatus === "convert") {
const newUploadData = {
...getState().files.uploadData,
...{
uploadedFiles: uploadedFiles + 1,
percent: newPercent,
uploaded: true,
},
};
updateConvertProgress(newUploadData, t, dispatch);
startSessionFunc(0, t, dispatch, getState);
} else if (uploadStatus === "pending") {
const stateUploadData = getState().files.uploadData;
const newUploadData = {
...stateUploadData,
...{
uploadStatus: null,
uploadedFiles: uploadedFiles + 1,
percent: newPercent,
uploaded: true,
},
};
updateConvertProgress(newUploadData, t, dispatch);
} else {
const newUploadData = {
...getState().files.uploadData,
...{ uploadedFiles: uploadedFiles + 1, percent: newPercent },
};
updateConvertProgress(newUploadData, t, dispatch);
updateFiles(toFolderId, dispatch, getState);
}
}
} else {
const newUploadData = {
...getState().files.uploadData,
...{ uploadedFiles: uploadedFiles + 1, percent: newPercent },
};
updateConvertProgress(newUploadData, t, dispatch);
console.log("Start session func ", newUploadData, indexOfFile + 1);
startSessionFunc(indexOfFile + 1, t, dispatch, getState);
}
})
.catch((err) => {
dispatch(
@ -868,155 +1114,7 @@ const startSessionFunc = (indexOfFile, t, dispatch, getState) => {
//toastr.error(err);
setTimeout(() => dispatch(clearPrimaryProgressData()), TIMEOUT);
});
};
const sendChunk = (
files,
location,
requestsDataArray,
indexOfFile,
t,
dispatch,
getState
) => {
const state = getState();
const { uploadData } = state.files;
const {
uploaded,
percent,
uploadedFiles,
//filesSize,
//convertFilesSize,
} = uploadData;
//const totalSize = convertFilesSize + filesSize;
let newPercent = percent;
const file =
uploadData.files[indexOfFile] || uploadData.convertFiles[indexOfFile];
const toFolderId = file.toFolderId;
const sendRequestFunc = (index) => {
api.files
.uploadFile(location, requestsDataArray[index])
.then((res) => {
//percent problem? use getState()
const newState = getState();
const newFilesLength = newState.files.uploadData.files.length;
const newTotalSize = sumBy(
newState.files.uploadData.files,
(f) => f.file.size
);
//console.log("newTotalSize ", newTotalSize);
let isLatestFile = indexOfFile === newFilesLength - 1;
const fileId = res.data.data.id;
const totalUploadedFiles = newState.files.uploadData.files.filter(
(_, i) => i < indexOfFile
);
//console.log("indexOfFile ", indexOfFile);
//console.log("totalUploadedFiles ", totalUploadedFiles);
const totalUploadedSize = sumBy(totalUploadedFiles, (f) => f.file.size);
//console.log("totalUploadedSize ", totalUploadedSize);
if (index < requestsDataArray.length) {
//newPercent = (index / requestsDataArray.length) * 100;
newPercent =
((index * chunkSize + totalUploadedSize) / newTotalSize) * 100;
}
/*if (res.data.data && res.data.data.uploaded) {
newPercent = (currentFile.size / newTotalSize) * 100;
}*/
//console.log("newPercent", newPercent);
if (index + 1 !== requestsDataArray.length) {
dispatch(
setPrimaryProgressBarData({
icon: "upload",
label: t("UploadingLabel", {
file: uploadedFiles,
totalFiles: files.length,
}),
percent: newPercent,
visible: true,
alert: false,
})
);
sendRequestFunc(index + 1);
} else if (uploaded) {
api.files.convertFile(fileId).then((convertRes) => {
if (convertRes && convertRes[0] && convertRes[0].progress !== 100) {
uploadData.percent = newPercent;
getConvertProgress(
fileId,
t,
uploadData,
isLatestFile,
indexOfFile,
dispatch,
getState
);
}
});
} else if (isLatestFile) {
if (uploaded) {
updateFiles(toFolderId, dispatch, getState);
} else {
const uploadStatus = getState().files.uploadData.uploadStatus;
if (uploadStatus === "convert") {
const newUploadData = {
...getState().files.uploadData,
...{
uploadedFiles: uploadedFiles + 1,
percent: newPercent,
uploaded: true,
},
};
updateConvertProgress(newUploadData, t, dispatch);
startSessionFunc(0, t, dispatch, getState);
} else if (uploadStatus === "pending") {
const stateUploadData = getState().files.uploadData;
const newUploadData = {
...stateUploadData,
...{
uploadStatus: null,
uploadedFiles: uploadedFiles + 1,
percent: newPercent,
uploaded: true,
},
};
updateConvertProgress(newUploadData, t, dispatch);
} else {
const newUploadData = {
...getState().files.uploadData,
...{ uploadedFiles: uploadedFiles + 1, percent: newPercent },
};
updateConvertProgress(newUploadData, t, dispatch);
updateFiles(toFolderId, dispatch, getState);
}
}
} else {
const newUploadData = {
...getState().files.uploadData,
...{ uploadedFiles: uploadedFiles + 1, percent: newPercent },
};
updateConvertProgress(newUploadData, t, dispatch);
console.log("Start session func ", newUploadData, indexOfFile + 1);
startSessionFunc(indexOfFile + 1, t, dispatch, getState);
}
})
.catch((err) => {
dispatch(
setPrimaryProgressBarData({
visible: true,
alert: true,
})
);
//toastr.error(err);
setTimeout(() => dispatch(clearPrimaryProgressData()), TIMEOUT);
});
};
sendRequestFunc(0);
};
};*/
const updateFiles = (folderId, dispatch, getState) => {
//console.log("folderId ", folderId);