mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Refactor uploads to same JS file
This commit is contained in:
parent
9b7ddbfe1e
commit
d7bee5a7b8
@ -1,90 +1,207 @@
|
|||||||
async function uploadFile(type) {
|
async function uploadFile(type, file = null, path = null, file_num = 0, _onProgress) {
|
||||||
file = $("#file")[0].files[0]
|
if (file == null) {
|
||||||
const fileId = uuidv4();
|
try {
|
||||||
const token = getCookie("_xsrf")
|
file = $("#file")[0].files[0];
|
||||||
document.getElementById("upload_input").innerHTML = '<div class="progress" style="width: 100%;"><div id="upload-progress-bar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <i class="fa-solid fa-spinner"></i></div></div>'
|
} catch {
|
||||||
if (!file) {
|
bootbox.alert("Please select a file first.")
|
||||||
alert("Please select a file first.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
const fileId = uuidv4();
|
||||||
|
const token = getCookie("_xsrf");
|
||||||
|
if (type !== "server_upload") {
|
||||||
|
document.getElementById("upload_input").innerHTML = '<div class="progress" style="width: 100%;"><div id="upload-progress-bar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <i class="fa-solid fa-spinner"></i></div></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = ``
|
||||||
|
if (type === "server_upload") {
|
||||||
|
url = `/api/v2/servers/${serverId}/files/upload/`;
|
||||||
|
} else if (type === "background") {
|
||||||
|
url = `/api/v2/crafty/admin/upload/`
|
||||||
|
} else if (type === "import") {
|
||||||
|
url = `/api/v2/servers/import/upload/`
|
||||||
|
}
|
||||||
|
console.log(url)
|
||||||
const chunkSize = 1024 * 1024; // 1MB
|
const chunkSize = 1024 * 1024; // 1MB
|
||||||
const totalChunks = Math.ceil(file.size / chunkSize);
|
const totalChunks = Math.ceil(file.size / chunkSize);
|
||||||
|
const file_hash = await calculateFileHash(file);
|
||||||
|
|
||||||
const uploadPromises = [];
|
const uploadPromises = [];
|
||||||
let res = await fetch(`/api/v2/servers/import/upload/`, {
|
let errors = []; // Array to store errors
|
||||||
|
try {
|
||||||
|
let res = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'X-XSRFToken': token,
|
'X-XSRFToken': token,
|
||||||
'chunked': true,
|
'chunked': true,
|
||||||
|
'fileHash': file_hash,
|
||||||
'fileSize': file.size,
|
'fileSize': file.size,
|
||||||
'type': type,
|
'type': type,
|
||||||
'total_chunks': totalChunks,
|
'total_chunks': totalChunks,
|
||||||
'filename': file.name,
|
'filename': file.name,
|
||||||
|
'location': path,
|
||||||
'fileId': fileId,
|
'fileId': fileId,
|
||||||
},
|
},
|
||||||
body: null,
|
body: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
let errorResponse = await res.json();
|
||||||
|
throw new Error(JSON.stringify(errorResponse));
|
||||||
|
}
|
||||||
|
|
||||||
let responseData = await res.json();
|
let responseData = await res.json();
|
||||||
|
|
||||||
let file_id = ""
|
if (responseData.status !== "ok") {
|
||||||
if (responseData.status === "ok") {
|
throw new Error(JSON.stringify(responseData));
|
||||||
file_id = responseData.data["file-id"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < totalChunks; i++) {
|
for (let i = 0; i < totalChunks; i++) {
|
||||||
const start = i * chunkSize;
|
const start = i * chunkSize;
|
||||||
const end = Math.min(start + chunkSize, file.size);
|
const end = Math.min(start + chunkSize, file.size);
|
||||||
const chunk = file.slice(start, end);
|
const chunk = file.slice(start, end);
|
||||||
|
const chunk_hash = await calculateFileHash(chunk);
|
||||||
|
|
||||||
const uploadPromise = fetch(`/api/v2/servers/import/upload/`, {
|
const uploadPromise = fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: chunk,
|
body: chunk,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Range': `bytes ${start}-${end - 1}/${file.size}`,
|
'Content-Range': `bytes ${start}-${end - 1}/${file.size}`,
|
||||||
'Content-Length': chunk.size,
|
'Content-Length': chunk.size,
|
||||||
'fileSize': file.size,
|
'fileSize': file.size,
|
||||||
|
'fileHash': file_hash,
|
||||||
|
'chunkHash': chunk_hash,
|
||||||
'chunked': true,
|
'chunked': true,
|
||||||
'type': type,
|
'type': type,
|
||||||
'total_chunks': totalChunks,
|
'total_chunks': totalChunks,
|
||||||
'filename': file.name,
|
'filename': file.name,
|
||||||
|
'location': path,
|
||||||
'fileId': fileId,
|
'fileId': fileId,
|
||||||
'chunkId': i,
|
'chunkId': i,
|
||||||
},
|
},
|
||||||
}).then(response => response.json())
|
})
|
||||||
|
.then(async response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorData = await response.json();
|
||||||
|
throw new Error(JSON.stringify(errorData) || 'Unknown error occurred');
|
||||||
|
}
|
||||||
|
return response.json(); // Return the JSON data
|
||||||
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.status === "completed") {
|
if (data.status !== "completed" && data.status !== "partial") {
|
||||||
|
throw new Error(data.message || 'Unknown error occurred');
|
||||||
|
}
|
||||||
|
// Update progress bar
|
||||||
|
const progress = (i + 1) / totalChunks * 100;
|
||||||
|
updateProgressBar(Math.round(progress), type, file_num);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
errors.push(error); // Store the error
|
||||||
|
});
|
||||||
|
|
||||||
|
uploadPromises.push(uploadPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(uploadPromises);
|
||||||
|
} catch (error) {
|
||||||
|
errors.push(error); // Store the error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.length > 0) {
|
||||||
|
const errorMessage = errors.map(error => JSON.parse(error.message).data.message || 'Unknown error occurred').join('<br>');
|
||||||
|
console.log(errorMessage)
|
||||||
|
bootbox.alert({
|
||||||
|
title: 'Error',
|
||||||
|
message: errorMessage,
|
||||||
|
callback: function () {
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (type !== "server_upload") {
|
||||||
|
// All promises resolved successfully
|
||||||
$("#upload_input").html(`<div class="card-header header-sm d-flex justify-content-between align-items-center" style="width: 100%;"><input value="${file.name}" type="text" id="file-uploaded" disabled></input> 🔒</div>`);
|
$("#upload_input").html(`<div class="card-header header-sm d-flex justify-content-between align-items-center" style="width: 100%;"><input value="${file.name}" type="text" id="file-uploaded" disabled></input> 🔒</div>`);
|
||||||
if (type === "import") {
|
if (type === "import") {
|
||||||
document.getElementById("lower_half").style.visibility = "visible";
|
document.getElementById("lower_half").style.visibility = "visible";
|
||||||
document.getElementById("lower_half").hidden = false;
|
document.getElementById("lower_half").hidden = false;
|
||||||
} else if (type === "background") {
|
} else if (type === "background") {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
location.href = `/panel/custom_login`
|
location.href = `/panel/custom_login`;
|
||||||
}, 2000)
|
}, 2000);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (data.status !== "partial") {
|
} else {
|
||||||
throw new Error(data.message);
|
let caught = false;
|
||||||
}
|
let expanded = false;
|
||||||
// Update progress bar
|
|
||||||
const progress = (i + 1) / totalChunks * 100;
|
|
||||||
updateProgressBar(Math.round(progress));
|
|
||||||
});
|
|
||||||
|
|
||||||
uploadPromises.push(uploadPromise);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all(uploadPromises);
|
expanded = document.getElementById(path).classList.contains("clicked");
|
||||||
} catch (error) {
|
} catch { }
|
||||||
bootbox.alert("Error uploading file: " + error.message);
|
|
||||||
|
let par_el;
|
||||||
|
let items;
|
||||||
|
try {
|
||||||
|
par_el = document.getElementById(path + "ul");
|
||||||
|
items = par_el.children;
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
caught = true;
|
||||||
|
par_el = document.getElementById("files-tree");
|
||||||
|
items = par_el.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = file.name;
|
||||||
|
let full_path = path + '/' + name;
|
||||||
|
let flag = false;
|
||||||
|
|
||||||
|
for (let k = 0; k < items.length; ++k) {
|
||||||
|
if ($(items[k]).attr("data-name") == name) {
|
||||||
|
flag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProgressBar(progress) {
|
if (!flag) {
|
||||||
|
if (caught && !expanded) {
|
||||||
|
$(par_el).append(`<li id="${full_path}li" class="d-block tree-ctx-item tree-file tree-item" data-path="${full_path}" data-name="${name}" onclick="clickOnFile(event)"><span style="margin-right: 6px;"><i class="far fa-file"></i></span>${name}</li>`);
|
||||||
|
} else if (expanded) {
|
||||||
|
$(par_el).append(`<li id="${full_path}li" class="tree-ctx-item tree-file tree-item" data-path="${full_path}" data-name="${name}" onclick="clickOnFile(event)"><span style="margin-right: 6px;"><i class="far fa-file"></i></span>${name}</li>`);
|
||||||
|
}
|
||||||
|
setTreeViewContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(`#upload-progress-bar-${file_num + 1}`).removeClass("progress-bar-striped");
|
||||||
|
$(`#upload-progress-bar-${file_num + 1}`).addClass("bg-success");
|
||||||
|
$(`#upload-progress-bar-${file_num + 1}`).html('<i style="color: black;" class="fas fa-box-check"></i>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function calculateFileHash(file) {
|
||||||
|
const arrayBuffer = await file.arrayBuffer();
|
||||||
|
const hashBuffer = await crypto.subtle.digest('SHA-256', arrayBuffer);
|
||||||
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||||
|
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
|
||||||
|
return hashHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateProgressBar(progress, type, i) {
|
||||||
|
if (type !== "server_upload") {
|
||||||
|
if (progress === 100) {
|
||||||
|
$(`#upload-progress-bar`).removeClass("progress-bar-striped")
|
||||||
|
|
||||||
|
$(`#upload-progress-bar`).removeClass("progress-bar-animated")
|
||||||
|
}
|
||||||
$(`#upload-progress-bar`).css('width', progress + '%');
|
$(`#upload-progress-bar`).css('width', progress + '%');
|
||||||
$(`#upload-progress-bar`).html(progress + '%');
|
$(`#upload-progress-bar`).html(progress + '%');
|
||||||
|
} else {
|
||||||
|
if (progress === 100) {
|
||||||
|
$(`#upload-progress-bar-${i + 1}`).removeClass("progress-bar-striped")
|
||||||
|
|
||||||
|
$(`#upload-progress-bar-${i + 1}`).removeClass("progress-bar-animated")
|
||||||
|
}
|
||||||
|
$(`#upload-progress-bar-${i + 1}`).css('width', progress + '%');
|
||||||
|
$(`#upload-progress-bar-${i + 1}`).html(progress + '%');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function uuidv4() {
|
function uuidv4() {
|
||||||
|
@ -723,131 +723,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadFile(file, path, file_num, onProgress) {
|
|
||||||
const fileId = uuidv4();
|
|
||||||
const token = getCookie("_xsrf")
|
|
||||||
if (!file) {
|
|
||||||
alert("Please select a file first.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const chunkSize = 1024 * 1024; // 1MB
|
|
||||||
const totalChunks = Math.ceil(file.size / chunkSize);
|
|
||||||
|
|
||||||
const uploadPromises = [];
|
|
||||||
let res = await fetch(`/api/v2/servers/${serverId}/files/upload/`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'X-XSRFToken': token,
|
|
||||||
'chunked': true,
|
|
||||||
'type': "server_upload",
|
|
||||||
'fileSize': file.size,
|
|
||||||
'total_chunks': totalChunks,
|
|
||||||
'location': path,
|
|
||||||
'filename': file.name,
|
|
||||||
'fileId': fileId,
|
|
||||||
},
|
|
||||||
body: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
let responseData = await res.json();
|
|
||||||
|
|
||||||
let file_id = ""
|
|
||||||
if (responseData.status === "ok") {
|
|
||||||
file_id = responseData.data["file-id"]
|
|
||||||
}
|
|
||||||
for (let i = 0; i < totalChunks; i++) {
|
|
||||||
const start = i * chunkSize;
|
|
||||||
const end = Math.min(start + chunkSize, file.size);
|
|
||||||
const chunk = file.slice(start, end);
|
|
||||||
|
|
||||||
const uploadPromise = fetch(`/api/v2/servers/${serverId}/files/upload/`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: chunk,
|
|
||||||
headers: {
|
|
||||||
'Content-Range': `bytes ${start}-${end - 1}/${file.size}`,
|
|
||||||
'Content-Length': chunk.size,
|
|
||||||
'chunked': true,
|
|
||||||
'type': "server_upload",
|
|
||||||
'fileSize': file.size,
|
|
||||||
'total_chunks': totalChunks,
|
|
||||||
'filename': file.name,
|
|
||||||
'location': path,
|
|
||||||
'fileId': fileId,
|
|
||||||
'chunkId': i,
|
|
||||||
},
|
|
||||||
}).then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.status === "completed") {
|
|
||||||
let caught = false;
|
|
||||||
try {
|
|
||||||
if (document.getElementById(path).classList.contains("clicked")) {
|
|
||||||
var expanded = true;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
var expanded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var par_el = document.getElementById(path + "ul");
|
|
||||||
var items = par_el.children;
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err)
|
|
||||||
caught = true;
|
|
||||||
var par_el = document.getElementById("files-tree");
|
|
||||||
var items = par_el.children;
|
|
||||||
}
|
|
||||||
let name = file.name;
|
|
||||||
console.log(par_el)
|
|
||||||
let full_path = path + '/' + name
|
|
||||||
let flag = false;
|
|
||||||
for (var k = 0; k < items.length; ++k) {
|
|
||||||
if ($(items[k]).attr("data-name") == name) {
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!flag) {
|
|
||||||
if (caught && expanded == false) {
|
|
||||||
$(par_el).append('<li id=' + '"' + full_path.toString() + 'li' + '"' + 'class="d-block tree-ctx-item tree-file tree-item" data-path=' + '"' + full_path.toString() + '"' + ' data-name=' + '"' + name.toString() + '"' + ' onclick="clickOnFile(event)" ><span style="margin-right: 6px;"><i class="far fa-file"></i></span>' + name + '</li>');
|
|
||||||
} else if (expanded == true) {
|
|
||||||
$(par_el).append('<li id=' + '"' + full_path.toString() + 'li' + '"' + 'class="tree-ctx-item tree-file tree-item" data-path=' + '"' + full_path.toString() + '"' + ' data-name=' + '"' + name.toString() + '"' + ' onclick="clickOnFile(event)" ><span style="margin-right: 6px;"><i class="far fa-file"></i></span>' + name + '</li>');
|
|
||||||
}
|
|
||||||
setTreeViewContext();
|
|
||||||
}
|
|
||||||
$(`#upload-progress-bar-${i + 1}`).removeClass("progress-bar-striped");
|
|
||||||
$(`#upload-progress-bar-${i + 1}`).addClass("bg-success");
|
|
||||||
$(`#upload-progress-bar-${i + 1}`).html('<i style="color: black;" class="fas fa-box-check"></i>')
|
|
||||||
} else if (data.status !== "partial") {
|
|
||||||
throw new Error(data.message);
|
|
||||||
}
|
|
||||||
// Update progress bar
|
|
||||||
const progress = (i + 1) / totalChunks * 100;
|
|
||||||
updateProgressBar(Math.round(progress), file_num);
|
|
||||||
});
|
|
||||||
|
|
||||||
uploadPromises.push(uploadPromise);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Promise.all(uploadPromises);
|
|
||||||
} catch (error) {
|
|
||||||
alert("Error uploading file: " + error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function updateProgressBar(progress, i) {
|
|
||||||
$(`#upload-progress-bar-${i + 1}`).css('width', progress + '%');
|
|
||||||
$(`#upload-progress-bar-${i + 1}`).html(progress + '%');
|
|
||||||
}
|
|
||||||
function uuidv4() {
|
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
||||||
const r = Math.random() * 16 | 0,
|
|
||||||
v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
||||||
return v.toString(16);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let uploadWaitDialog;
|
let uploadWaitDialog;
|
||||||
let doUpload = true;
|
|
||||||
|
|
||||||
async function uploadFilesE(event) {
|
async function uploadFilesE(event) {
|
||||||
path = event.target.parentElement.getAttribute('data-path');
|
path = event.target.parentElement.getAttribute('data-path');
|
||||||
@ -907,19 +783,17 @@
|
|||||||
|
|
||||||
$('#upload-progress-bar-parent').append(progressHtml);
|
$('#upload-progress-bar-parent').append(progressHtml);
|
||||||
|
|
||||||
const uploadPromise = uploadFile(file, path, i, (progress) => {
|
const uploadPromise = uploadFile("server_upload", file, path, i, (progress) => {
|
||||||
$(`#upload-progress-bar-${i + 1}`).attr('aria-valuenow', progress)
|
$(`#upload-progress-bar-${i + 1}`).attr('aria-valuenow', progress)
|
||||||
$(`#upload-progress-bar-${i + 1}`).css('width', progress + '%');
|
$(`#upload-progress-bar-${i + 1}`).css('width', progress + '%');
|
||||||
});
|
});
|
||||||
uploadPromises.push(uploadPromise);
|
uploadPromises.push(uploadPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
await Promise.all(uploadPromises);
|
await Promise.all(uploadPromises);
|
||||||
hideUploadBox();
|
hideUploadBox();
|
||||||
} catch (error) {
|
|
||||||
alert("Error uploading file: " + error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -927,6 +801,15 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function calculateFileHash(file) {
|
||||||
|
const arrayBuffer = await file.arrayBuffer();
|
||||||
|
const hashBuffer = await crypto.subtle.digest('SHA-256', arrayBuffer);
|
||||||
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||||
|
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
|
||||||
|
return hashHex;
|
||||||
|
}
|
||||||
|
|
||||||
function getDirView(event) {
|
function getDirView(event) {
|
||||||
let path = event.target.parentElement.getAttribute("data-path");
|
let path = event.target.parentElement.getAttribute("data-path");
|
||||||
if (document.getElementById(path).classList.contains('clicked')) {
|
if (document.getElementById(path).classList.contains('clicked')) {
|
||||||
@ -1232,5 +1115,5 @@
|
|||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<script src="../../static/assets/js/shared/upload.js"></script>
|
||||||
{% end %}
|
{% end %}
|
Loading…
Reference in New Issue
Block a user