mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-04 06:37:38 +03:00
Allow any file to be uploaded (#84)
## Summary - Allow any file to be uploaded - Removes .epub restriction ## Additional Context - Fixes #74
This commit is contained in:
parent
926c786705
commit
9b4dfbd180
@ -513,13 +513,6 @@ void CrossPointWebServer::handleUpload() {
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] START: %s to path: %s\n", millis(), uploadFileName.c_str(), uploadPath.c_str());
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] Free heap: %d bytes\n", millis(), ESP.getFreeHeap());
|
||||
|
||||
// Validate file extension
|
||||
if (!isEpubFile(uploadFileName)) {
|
||||
uploadError = "Only .epub files are allowed";
|
||||
Serial.printf("[%lu] [WEB] [UPLOAD] REJECTED - not an epub file\n", millis());
|
||||
return;
|
||||
}
|
||||
|
||||
// Create file path
|
||||
String filePath = uploadPath;
|
||||
if (!filePath.endsWith("/")) filePath += "/";
|
||||
|
||||
@ -3,15 +3,15 @@
|
||||
CrossPoint E-Reader • Open Source
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Upload Modal -->
|
||||
<div class="modal-overlay" id="uploadModal">
|
||||
<div class="modal">
|
||||
<button class="modal-close" onclick="closeUploadModal()">×</button>
|
||||
<h3>📤 Upload eBook</h3>
|
||||
<h3>📤 Upload file</h3>
|
||||
<div class="upload-form">
|
||||
<p class="file-info">Select an .epub file to upload to <strong id="uploadPathDisplay"></strong></p>
|
||||
<input type="file" id="fileInput" accept=".epub" onchange="validateFile()">
|
||||
<p class="file-info">Select a file to upload to <strong id="uploadPathDisplay"></strong></p>
|
||||
<input type="file" id="fileInput" onchange="validateFile()">
|
||||
<button id="uploadBtn" class="upload-btn" onclick="uploadFile()" disabled>Upload</button>
|
||||
<div id="progress-container">
|
||||
<div id="progress-bar"><div id="progress-fill"></div></div>
|
||||
@ -20,7 +20,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- New Folder Modal -->
|
||||
<div class="modal-overlay" id="folderModal">
|
||||
<div class="modal">
|
||||
@ -33,7 +33,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Delete Confirmation Modal -->
|
||||
<div class="modal-overlay" id="deleteModal">
|
||||
<div class="modal">
|
||||
@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
// Modal functions
|
||||
function openUploadModal() {
|
||||
@ -58,7 +58,7 @@
|
||||
document.getElementById('uploadPathDisplay').textContent = currentPath === '/' ? '/ 🏠' : currentPath;
|
||||
document.getElementById('uploadModal').classList.add('open');
|
||||
}
|
||||
|
||||
|
||||
function closeUploadModal() {
|
||||
document.getElementById('uploadModal').classList.remove('open');
|
||||
document.getElementById('fileInput').value = '';
|
||||
@ -67,18 +67,18 @@
|
||||
document.getElementById('progress-fill').style.width = '0%';
|
||||
document.getElementById('progress-fill').style.backgroundColor = '#27ae60';
|
||||
}
|
||||
|
||||
|
||||
function openFolderModal() {
|
||||
const currentPath = document.getElementById('currentPath').value;
|
||||
document.getElementById('folderPathDisplay').textContent = currentPath === '/' ? '/ 🏠' : currentPath;
|
||||
document.getElementById('folderModal').classList.add('open');
|
||||
document.getElementById('folderName').value = '';
|
||||
}
|
||||
|
||||
|
||||
function closeFolderModal() {
|
||||
document.getElementById('folderModal').classList.remove('open');
|
||||
}
|
||||
|
||||
|
||||
// Close modals when clicking overlay
|
||||
document.querySelectorAll('.modal-overlay').forEach(function(overlay) {
|
||||
overlay.addEventListener('click', function(e) {
|
||||
@ -87,58 +87,40 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
function validateFile() {
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
const uploadBtn = document.getElementById('uploadBtn');
|
||||
const file = fileInput.files[0];
|
||||
|
||||
if (file) {
|
||||
const fileName = file.name.toLowerCase();
|
||||
if (!fileName.endsWith('.epub')) {
|
||||
alert('Only .epub files are allowed!');
|
||||
fileInput.value = '';
|
||||
uploadBtn.disabled = true;
|
||||
return;
|
||||
}
|
||||
uploadBtn.disabled = false;
|
||||
} else {
|
||||
uploadBtn.disabled = true;
|
||||
}
|
||||
uploadBtn.disabled = !file;
|
||||
}
|
||||
|
||||
|
||||
function uploadFile() {
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
const file = fileInput.files[0];
|
||||
const currentPath = document.getElementById('currentPath').value;
|
||||
|
||||
|
||||
if (!file) {
|
||||
alert('Please select a file first!');
|
||||
return;
|
||||
}
|
||||
|
||||
const fileName = file.name.toLowerCase();
|
||||
if (!fileName.endsWith('.epub')) {
|
||||
alert('Only .epub files are allowed!');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
|
||||
const progressContainer = document.getElementById('progress-container');
|
||||
const progressFill = document.getElementById('progress-fill');
|
||||
const progressText = document.getElementById('progress-text');
|
||||
const uploadBtn = document.getElementById('uploadBtn');
|
||||
|
||||
|
||||
progressContainer.style.display = 'block';
|
||||
uploadBtn.disabled = true;
|
||||
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
// Include path as query parameter since multipart form data doesn't make
|
||||
// form fields available until after file upload completes
|
||||
xhr.open('POST', '/upload?path=' + encodeURIComponent(currentPath), true);
|
||||
|
||||
|
||||
xhr.upload.onprogress = function(e) {
|
||||
if (e.lengthComputable) {
|
||||
const percent = Math.round((e.loaded / e.total) * 100);
|
||||
@ -146,7 +128,7 @@
|
||||
progressText.textContent = 'Uploading: ' + percent + '%';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
progressText.textContent = 'Upload complete!';
|
||||
@ -159,39 +141,39 @@
|
||||
uploadBtn.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
xhr.onerror = function() {
|
||||
progressText.textContent = 'Upload failed - network error';
|
||||
progressFill.style.backgroundColor = '#e74c3c';
|
||||
uploadBtn.disabled = false;
|
||||
};
|
||||
|
||||
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
|
||||
function createFolder() {
|
||||
const folderName = document.getElementById('folderName').value.trim();
|
||||
const currentPath = document.getElementById('currentPath').value;
|
||||
|
||||
|
||||
if (!folderName) {
|
||||
alert('Please enter a folder name!');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Validate folder name (no special characters except underscore and hyphen)
|
||||
const validName = /^[a-zA-Z0-9_\-]+$/.test(folderName);
|
||||
if (!validName) {
|
||||
alert('Folder name can only contain letters, numbers, underscores, and hyphens.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('name', folderName);
|
||||
formData.append('path', currentPath);
|
||||
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '/mkdir', true);
|
||||
|
||||
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
window.location.reload();
|
||||
@ -199,14 +181,14 @@
|
||||
alert('Failed to create folder: ' + xhr.responseText);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
xhr.onerror = function() {
|
||||
alert('Failed to create folder - network error');
|
||||
};
|
||||
|
||||
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
|
||||
// Delete functions
|
||||
function openDeleteModal(name, path, isFolder) {
|
||||
document.getElementById('deleteItemName').textContent = (isFolder ? '📁 ' : '📄 ') + name;
|
||||
@ -214,22 +196,22 @@
|
||||
document.getElementById('deleteItemType').value = isFolder ? 'folder' : 'file';
|
||||
document.getElementById('deleteModal').classList.add('open');
|
||||
}
|
||||
|
||||
|
||||
function closeDeleteModal() {
|
||||
document.getElementById('deleteModal').classList.remove('open');
|
||||
}
|
||||
|
||||
|
||||
function confirmDelete() {
|
||||
const path = document.getElementById('deleteItemPath').value;
|
||||
const itemType = document.getElementById('deleteItemType').value;
|
||||
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('path', path);
|
||||
formData.append('type', itemType);
|
||||
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '/delete', true);
|
||||
|
||||
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
window.location.reload();
|
||||
@ -238,12 +220,12 @@
|
||||
closeDeleteModal();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
xhr.onerror = function() {
|
||||
alert('Failed to delete - network error');
|
||||
closeDeleteModal();
|
||||
};
|
||||
|
||||
|
||||
xhr.send(formData);
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user