Add chunked uploads and raise storage rate to GHS 0.30/GB/month.
Deploy Ladill Transfer / deploy (push) Successful in 39s
Deploy Ladill Transfer / deploy (push) Successful in 39s
Large files upload in 5 MB chunks (hosting file manager pattern) for the transfer UI and Ladill Mail S2S API, with no app-level file size cap when TRANSFER_MAX_FILE_BYTES=0. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import './bootstrap';
|
||||
|
||||
import { registerLadillConfirmStore, registerLadillModalHelpers } from './ladill-modals';
|
||||
import { shouldUseChunkedUpload, uploadFileChunked } from './chunked-upload';
|
||||
|
||||
registerLadillModalHelpers();
|
||||
|
||||
@@ -300,6 +301,90 @@ Alpine.data('topbarSearch', (config = {}) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
Alpine.data('transferCreateForm', (config = {}) => ({
|
||||
selectedFiles: [],
|
||||
uploading: false,
|
||||
submitting: false,
|
||||
uploadProgress: 0,
|
||||
uploadLabel: '',
|
||||
prepared: false,
|
||||
|
||||
onFilesChange(event) {
|
||||
this.selectedFiles = Array.from(event.target.files || []);
|
||||
this.prepared = false;
|
||||
},
|
||||
|
||||
async submit(event) {
|
||||
if (this.prepared) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
const form = event.target;
|
||||
const fileInput = form.querySelector('#files');
|
||||
const files = this.selectedFiles.length
|
||||
? this.selectedFiles
|
||||
: Array.from(fileInput?.files || []);
|
||||
|
||||
if (!files.length) {
|
||||
window.alert('Add at least one file to share.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.uploading = true;
|
||||
this.uploadProgress = 0;
|
||||
const smallFiles = [];
|
||||
|
||||
try {
|
||||
form.querySelectorAll('input[name="upload_ids[]"]').forEach((node) => node.remove());
|
||||
|
||||
for (let index = 0; index < files.length; index++) {
|
||||
const file = files[index];
|
||||
this.uploadLabel = `Uploading ${file.name} (${index + 1}/${files.length})…`;
|
||||
|
||||
if (shouldUseChunkedUpload(file.size)) {
|
||||
const result = await uploadFileChunked(file, {
|
||||
initUrl: config.initUrl,
|
||||
chunkUrl: config.chunkUrl,
|
||||
finalizeUrl: config.finalizeUrl,
|
||||
csrfToken: config.csrfToken,
|
||||
onProgress: (percent) => {
|
||||
this.uploadProgress = percent;
|
||||
},
|
||||
});
|
||||
|
||||
const hidden = document.createElement('input');
|
||||
hidden.type = 'hidden';
|
||||
hidden.name = 'upload_ids[]';
|
||||
hidden.value = result.uploadId;
|
||||
form.appendChild(hidden);
|
||||
} else {
|
||||
smallFiles.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (fileInput && smallFiles.length) {
|
||||
const dataTransfer = new DataTransfer();
|
||||
smallFiles.forEach((file) => dataTransfer.items.add(file));
|
||||
fileInput.files = dataTransfer.files;
|
||||
} else if (fileInput) {
|
||||
fileInput.removeAttribute('required');
|
||||
fileInput.value = '';
|
||||
}
|
||||
|
||||
this.uploading = false;
|
||||
this.submitting = true;
|
||||
this.prepared = true;
|
||||
form.submit();
|
||||
} catch (error) {
|
||||
this.uploading = false;
|
||||
this.submitting = false;
|
||||
this.prepared = false;
|
||||
window.alert(error?.message || 'Upload failed. Please try again.');
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
window.Alpine = Alpine;
|
||||
registerLadillConfirmStore(Alpine);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user