WIP file drop server, no downloads yet
This commit is contained in:
commit
20da86132b
12 changed files with 3294 additions and 0 deletions
22
static/index.html
Normal file
22
static/index.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<link rel="stylesheet" type="text/css" href="transbeam.css"/>
|
||||
<title>Upload Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<label>
|
||||
<span class="fake_button" id="file_input_message">Select files to upload...</span>
|
||||
<input type="file" multiple id="file_input"/>
|
||||
</label>
|
||||
</div>
|
||||
<button id="upload" disabled>Upload</button>
|
||||
<h2>Files selected:</h2>
|
||||
<ul id="file_list">
|
||||
</ul>
|
||||
<script src="upload.js"></script>
|
||||
</body>
|
||||
</html>
|
24
static/transbeam.css
Normal file
24
static/transbeam.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button, .fake_button {
|
||||
font-size: 18px;
|
||||
font-family: sans-serif;
|
||||
color: #000;
|
||||
background-color: #ccc;
|
||||
border: 1px solid #bbb;
|
||||
border-radius: 4px;
|
||||
padding: 6px 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover, .fake_button:hover {
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
button:disabled, button:disabled:hover {
|
||||
color: #aaa;
|
||||
background-color: #eee;
|
||||
border-color: #ddd;
|
||||
}
|
105
static/upload.js
Normal file
105
static/upload.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
let files = [];
|
||||
|
||||
let socket = null;
|
||||
let fileIndex = 0;
|
||||
let byteIndex = 0;
|
||||
|
||||
function sendMetadata() {
|
||||
const metadata = files.map((file) => ({
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
modtime: file.lastModified,
|
||||
}));
|
||||
socket.send(JSON.stringify(metadata));
|
||||
}
|
||||
|
||||
function finishSending() {
|
||||
if (socket.bufferedAmount > 0) {
|
||||
window.setTimeout(finishSending, 1000);
|
||||
return;
|
||||
}
|
||||
socket.close();
|
||||
alert("done");
|
||||
}
|
||||
|
||||
function sendData() {
|
||||
if (fileIndex >= files.length) {
|
||||
finishSending();
|
||||
}
|
||||
const currentFile = files[fileIndex];
|
||||
if (byteIndex < currentFile.size) {
|
||||
const endpoint = Math.min(byteIndex+8192, currentFile.size);
|
||||
const data = currentFile.slice(byteIndex, endpoint);
|
||||
socket.send(data);
|
||||
byteIndex = endpoint;
|
||||
} else {
|
||||
fileIndex += 1;
|
||||
byteIndex = 0;
|
||||
sendData();
|
||||
}
|
||||
}
|
||||
|
||||
const fileInput = document.getElementById('file_input');
|
||||
const fileInputMessage = document.getElementById('file_input_message');
|
||||
const fileList = document.getElementById('file_list');
|
||||
const uploadButton = document.getElementById('upload');
|
||||
|
||||
function updateButtons() {
|
||||
if (files.length === 0) {
|
||||
uploadButton.disabled = true;
|
||||
fileInputMessage.textContent = 'Select files to upload...';
|
||||
} else {
|
||||
uploadButton.disabled = false;
|
||||
fileInputMessage.textContent = 'Select more files to upload...';
|
||||
}
|
||||
}
|
||||
|
||||
updateButtons();
|
||||
|
||||
function addFile(newFile) {
|
||||
if (files.some((oldFile) => newFile.name === oldFile.name)) { return; }
|
||||
|
||||
files.push(newFile);
|
||||
|
||||
const listEntry = document.createElement('li');
|
||||
const deleteButton = document.createElement('button');
|
||||
deleteButton.textContent = 'x';
|
||||
deleteButton.addEventListener('click', () => {
|
||||
removeFile(newFile.name);
|
||||
listEntry.remove();
|
||||
updateButtons();
|
||||
});
|
||||
const entryName = document.createElement('span');
|
||||
entryName.textContent = newFile.name;
|
||||
listEntry.appendChild(deleteButton);
|
||||
listEntry.appendChild(entryName);
|
||||
|
||||
fileList.appendChild(listEntry);
|
||||
}
|
||||
|
||||
function removeFile(name) {
|
||||
files = files.filter((file) => file.name !== name);
|
||||
}
|
||||
|
||||
fileInput.addEventListener('input', (e) => {
|
||||
for (const file of e.target.files) { addFile(file); }
|
||||
updateButtons();
|
||||
e.target.value = '';
|
||||
});
|
||||
|
||||
uploadButton.addEventListener('click', (e) => {
|
||||
if (files.length === 0) { return; }
|
||||
|
||||
fileInput.disabled = true;
|
||||
for (const button of document.getElementsByTagName('button')) {
|
||||
button.disabled = true;
|
||||
}
|
||||
|
||||
socket = new WebSocket('ws://localhost:3000/upload');
|
||||
socket.addEventListener('open', sendMetadata);
|
||||
socket.addEventListener('message', (msg) => {
|
||||
if (msg.data === 'ack') {
|
||||
sendData();
|
||||
}
|
||||
});
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue