Compare commits

..

No commits in common. "acd58dbaa5dfd0d754b37d2e983061711a92814d" and "55fa969bead36745e2e271d7b3eb9716720af17d" have entirely different histories.

4 changed files with 39 additions and 173 deletions

View file

@ -4,41 +4,21 @@
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" type="text/css" href="transbeam.css"/> <link rel="stylesheet" type="text/css" href="transbeam.css"/>
<script src="util.js"></script>
<title>Upload Test</title> <title>Upload Test</title>
</head> </head>
<body> <body>
<div id="header"> <div>
<img src="transbeam.svg" height="128"> <label>
<h1>transbeam</h1> <input type="file" multiple id="file_input"/>
</div> <span class="fake_button" id="file_input_message">Select files to upload...</span>
</label>
<noscript>This page requires Javascript :(</noscript> </div>
<button id="upload" disabled>Upload</button>
<button id="upload">Upload</button> <h2>Files selected:</h2>
<div id="download_link_container" style="display: none;"> <ul id="file_list">
Download link: <span id="download_link"></span> </ul>
</div> <div id="download_link"></div>
<div id="progress_container" style="display: none;"> <div id="progress"></div>
<div id="progress"></div> <script src="upload.js"></script>
<div id="progress_bar">
<div id="progress_bar_filled"></div>
</div>
</div>
<div id="file_list_container" style="display: none;">
<table id="file_list">
</table>
</div>
<div id="file_input_container">
<label>
<input type="file" multiple id="file_input"/>
<span class="fake_button" id="file_input_message">Select files to upload...</span>
</label>
</div>
<div id="footer">
<h5>(c) 2022 xenofem, MIT licensed</h5>
<h5><a target="_blank" href="https://git.xeno.science/xenofem/transbeam">source</a></h5>
</div>
<script src="upload.js"></script>
</body> </body>
</html> </html>

View file

@ -1,58 +1,10 @@
body {
text-align: center;
font-family: sans-serif;
max-width: 512px;
margin: 0.5em auto;
padding: 0 1em;
}
#header h1 {
margin-top: 5px;
}
#progress_container {
margin: 10px auto;
}
#progress_bar, #progress_bar_filled {
height: 20px;
border-radius: 8px;
}
#progress_bar {
border: 1px solid #48f;
}
#progress_bar_filled {
width: 0;
background-color: #27f;
}
table {
border-collapse: collapse;
margin: 20px auto;
}
tr + tr td {
border-top: 1px solid #ddd;
}
td {
padding: 10px;
}
td.file_size {
text-align: right;
}
td.file_name {
text-align: left;
}
input[type="file"] { input[type="file"] {
display: none; display: none;
} }
button, .fake_button { button, .fake_button {
font-size: 18px; font-size: 18px;
font-family: sans-serif;
color: #000; color: #000;
background-color: #ccc; background-color: #ccc;
border: 1px solid #bbb; border: 1px solid #bbb;
@ -71,11 +23,3 @@ button:disabled, input:disabled + .fake_button {
border-color: #ddd; border-color: #ddd;
cursor: not-allowed; cursor: not-allowed;
} }
#footer {
margin-top: 30px;
}
#footer h5 {
margin: 5px auto;
}

View file

@ -1,21 +1,5 @@
const FILE_CHUNK_SIZE = 16384; const FILE_CHUNK_SIZE = 16384;
const fileInputContainer = document.getElementById('file_input_container');
const fileInput = document.getElementById('file_input');
const fileInputMessage = document.getElementById('file_input_message');
const fileListContainer = document.getElementById('file_list_container');
const fileList = document.getElementById('file_list');
const uploadButton = document.getElementById('upload');
const downloadLinkContainer = document.getElementById('download_link_container');
const downloadLink = document.getElementById('download_link');
const progressContainer = document.getElementById('progress_container');
const progress = document.getElementById('progress');
const progressBarFilled = document.getElementById('progress_bar_filled');
let files = []; let files = [];
let socket = null; let socket = null;
@ -39,7 +23,7 @@ function finishSending() {
return; return;
} }
socket.close(); socket.close();
progressContainer.textContent = "Upload complete!"; alert("done");
} }
function sendData() { function sendData() {
@ -54,7 +38,7 @@ function sendData() {
socket.send(data); socket.send(data);
byteIndex = endpoint; byteIndex = endpoint;
bytesSent += data.size; bytesSent += data.size;
updateProgress(); progress.textContent = `${Math.floor(bytesSent * 100 / totalBytes)}%`;
} else { } else {
fileIndex += 1; fileIndex += 1;
byteIndex = 0; byteIndex = 0;
@ -62,69 +46,42 @@ function sendData() {
} }
} }
function updateProgress() { const fileInput = document.getElementById('file_input');
let percentage; const fileInputMessage = document.getElementById('file_input_message');
if (totalBytes === 0) { const fileList = document.getElementById('file_list');
percentage = "0%"; const uploadButton = document.getElementById('upload');
} else { const downloadLink = document.getElementById('download_link');
percentage = `${(bytesSent*100/totalBytes).toFixed(1)}%`; const progress = document.getElementById('progress');
}
progress.textContent = percentage;
progressBarFilled.style.width = percentage;
}
function updateFiles() {
totalBytes = files.reduce((acc, file) => acc + file.size, 0);
function updateButtons() {
if (files.length === 0) { if (files.length === 0) {
uploadButton.disabled = true;
fileInputMessage.textContent = 'Select files to upload...'; fileInputMessage.textContent = 'Select files to upload...';
fileListContainer.style.display = 'none';
uploadButton.style.display = 'none';
} else { } else {
uploadButton.disabled = false;
fileInputMessage.textContent = 'Select more files to upload...'; fileInputMessage.textContent = 'Select more files to upload...';
fileListContainer.style.display = '';
uploadButton.textContent = `Upload ${files.length} file${files.length > 1 ? 's' : ''} (${displaySize(totalBytes)})`;
uploadButton.style.display = '';
} }
} }
updateFiles(); updateButtons();
downloadLinkContainer.style.display = 'none';
progressContainer.style.display = 'none';
function addFile(newFile) { function addFile(newFile) {
if (files.some((oldFile) => newFile.name === oldFile.name)) { return; } if (files.some((oldFile) => newFile.name === oldFile.name)) { return; }
files.push(newFile); files.push(newFile);
addListEntry(newFile); const listEntry = document.createElement('li');
}
function addListEntry(file) {
const listEntry = document.createElement('tr');
const deleteButtonCell = document.createElement('td');
const deleteButton = document.createElement('button'); const deleteButton = document.createElement('button');
deleteButtonCell.appendChild(deleteButton);
deleteButton.className = 'file_delete';
deleteButton.textContent = 'x'; deleteButton.textContent = 'x';
deleteButton.addEventListener('click', () => { deleteButton.addEventListener('click', () => {
removeFile(file.name); removeFile(newFile.name);
listEntry.remove(); listEntry.remove();
updateFiles(); updateButtons();
}); });
const entryName = document.createElement('span');
const sizeCell = document.createElement('td'); entryName.textContent = newFile.name;
sizeCell.className = 'file_size'; listEntry.appendChild(deleteButton);
sizeCell.textContent = displaySize(file.size); listEntry.appendChild(entryName);
const nameCell = document.createElement('td');
nameCell.className = 'file_name';
nameCell.textContent = file.name;
listEntry.appendChild(deleteButtonCell);
listEntry.appendChild(sizeCell);
listEntry.appendChild(nameCell);
fileList.appendChild(listEntry); fileList.appendChild(listEntry);
} }
@ -135,26 +92,25 @@ function removeFile(name) {
fileInput.addEventListener('input', (e) => { fileInput.addEventListener('input', (e) => {
for (const file of e.target.files) { addFile(file); } for (const file of e.target.files) { addFile(file); }
updateFiles(); updateButtons();
e.target.value = ''; e.target.value = '';
}); });
uploadButton.addEventListener('click', (e) => { uploadButton.addEventListener('click', (e) => {
if (files.length === 0) { return; } if (files.length === 0) { return; }
fileInputContainer.remove(); fileInput.disabled = true;
for (const button of Array.from(document.getElementsByTagName('button'))) { for (const button of document.getElementsByTagName('button')) {
button.remove(); button.disabled = true;
} }
totalBytes = files.reduce((acc, file) => acc + file.size, 0);
socket = new WebSocket(`${window.location.protocol === 'http:' ? 'ws' : 'wss'}://${window.location.host}/upload`); socket = new WebSocket(`${window.location.protocol === 'http:' ? 'ws' : 'wss'}://${window.location.host}/upload`);
socket.addEventListener('open', sendMetadata); socket.addEventListener('open', sendMetadata);
socket.addEventListener('message', (msg) => { socket.addEventListener('message', (msg) => {
if (bytesSent === 0 && msg.data.match(/^[A-Za-z0-9]+$/)) { if (bytesSent === 0 && msg.data.match(/^[A-Za-z0-9]+$/)) {
downloadLink.textContent = `${window.location.origin}/download/${msg.data}`; downloadLink.textContent = `${window.location.origin}/download/${msg.data}`;
downloadLinkContainer.style.display = '';
updateProgress();
progressContainer.style.display = '';
sendData(); sendData();
} else if (msg.data === 'ack') { } else if (msg.data === 'ack') {
sendData(); sendData();

View file

@ -1,14 +0,0 @@
const UNITS = [
{ name: 'GB', size: Math.pow(2, 30) },
{ name: 'MB', size: Math.pow(2, 20) },
{ name: 'KB', size: Math.pow(2, 10) },
];
function displaySize(bytes) {
for (const unit of UNITS) {
if (bytes >= unit.size) {
return `${(bytes / unit.size).toFixed(1)}${unit.name}`;
}
}
return `${bytes}B`;
}