Spaces:
Running
Running
!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
} | |
input, button, progress { | |
display: block; | |
margin-top: 10px; | |
} | |
#message { | |
margin-top: 20px; | |
color: blue; | |
} | |
#error { | |
color: red; | |
} | |
</style> | |
</head> | |
<body> | |
<label for="tokenInput">Hugging Face Token:</label> | |
<input type="password" id="tokenInput" name="tokenInput"> | |
<label for="repoInput">Repository ID:</label> | |
<input type="text" id="repoInput" name="repoInput" placeholder="my-user/nlp-model"> | |
<input type="file" id="fileUpload" multiple> | |
<button id="uploadButton">Upload Files</button> | |
<div id="processingMessage"></div> | |
<div style="display:flex"><progress id="progressBar" value="0" max="100"></progress><div id="uploadSpeed"></div></div> | |
<div id="message"></div> | |
<div id="error"></div> | |
<script type="module"> | |
import { createRepo, uploadFiles } from "https://cdn.jsdelivr.net/npm/@huggingface/hub@0.8.3/+esm"; | |
const uploadButton = document.getElementById('uploadButton'); | |
uploadButton.addEventListener('click', upload); | |
// Override global fetch | |
const originalFetch = window.fetch; | |
let uploadStartTime; | |
let uploadedBytes = 0; | |
let totalSize = 0; // Total size of the files | |
let uploadFinished = false; | |
window.fetch = function(url, init) { | |
if (typeof url === 'string' && init && init.method === 'PUT') { | |
uploadStartTime = uploadStartTime || Date.now(); | |
return new Promise((resolve, reject) => { | |
const xhr = new XMLHttpRequest(); | |
xhr.open(init.method, url); | |
for (let header in init.headers) { | |
xhr.setRequestHeader(header, init.headers[header]); | |
} | |
xhr.onload = () => { | |
resolve({ | |
ok: xhr.status >= 200 && xhr.status < 300, | |
status: xhr.status, | |
statusText: xhr.statusText, | |
text: () => Promise.resolve(xhr.responseText), | |
}); | |
}; | |
xhr.onerror = () => reject(new TypeError('Network request failed')); | |
xhr.ontimeout = () => reject(new TypeError('Network request failed due to timeout')); | |
xhr.upload.onprogress = (event) => { | |
if (event.lengthComputable) { | |
uploadedBytes += event.loaded; | |
const progress = uploadedBytes / totalSize; // Use the known total size | |
const progressBar = document.getElementById('progressBar'); | |
progressBar.value = progress * 100; | |
const speedDiv = document.getElementById('uploadSpeed'); | |
const processingMessage = document.getElementById('processingMessage'); | |
if (progress < 1) { // If upload is not yet finished | |
const elapsedTime = (Date.now() - uploadStartTime) / 1000; // in seconds | |
const speed = uploadedBytes / elapsedTime; // in bytes per second | |
speedDiv.textContent = `Upload speed: ${(speed / 1024 / 1024).toFixed(2)} MB/s`; | |
} else if (!uploadFinished) { // If upload just finished | |
uploadFinished = true; | |
speedDiv.textContent = ''; | |
processingMessage.textContent = "Processing your upload..."; | |
} | |
} | |
}; | |
xhr.send(init.body); | |
}); | |
} else { | |
return originalFetch(url, init); | |
} | |
} | |
async function upload() { | |
const fileInput = document.getElementById('fileUpload'); | |
const files = Array.from(fileInput.files); // convert FileList to Array | |
// Calculate total size of the files | |
totalSize = files.reduce((acc, file) => acc + file.size, 0); | |
const tokenInput = document.getElementById('tokenInput'); | |
const HF_ACCESS_TOKEN = tokenInput.value; // get the entered token | |
const repoInput = document.getElementById('repoInput'); | |
const REPO_ID = repoInput.value; // get the entered repo id | |
const progressBar = document.getElementById('progressBar'); | |
const messageDiv = document.getElementById('message'); | |
const errorDiv = document.getElementById('error'); | |
const processingMessage = document.getElementById('processingMessage'); | |
progressBar.value = 0; // reset progress bar | |
messageDiv.textContent = ''; // clear previous messages | |
errorDiv.textContent = ''; // clear previous errors | |
processingMessage.textContent = ''; // clear previous processing message | |
if (files.length > 0) { | |
// start time | |
const startTime = Date.now(); | |
try { | |
// Attempt to create the repo | |
await createRepo({ | |
repo: REPO_ID, | |
credentials: { accessToken: HF_ACCESS_TOKEN }, | |
}); | |
} catch (error) { | |
// If the repo already exists, we simply log and continue | |
if (error.message === 'You already created this model repo') { | |
console.log('Repository already exists, proceeding to upload files'); | |
} else { | |
console.error('Error creating repository', error); | |
errorDiv.textContent = 'Error creating repository'; | |
return; // stop if other errors occur during repository creation | |
} | |
} | |
try { | |
// upload files | |
await uploadFiles({ | |
repo: REPO_ID, | |
credentials: { accessToken: HF_ACCESS_TOKEN }, | |
files: files.map(file => ({path: file.name, content: file})) | |
}); | |
console.log(`All files uploaded successfully`); | |
// update progress bar | |
progressBar.value = 100; | |
} catch (error) { | |
console.error('Error uploading files', error); | |
errorDiv.textContent = 'Error uploading files'; | |
return; // stop uploading further files on error | |
} | |
// calculate elapsed time and speed | |
const elapsedTime = (Date.now() - startTime) / 1000; // in seconds | |
let speed = uploadedBytes / elapsedTime; // in bytes per second | |
// Convert totalSize and speed to MB and MB/s respectively | |
totalSize = totalSize / (1024 * 1024); // convert to MB | |
speed = speed / (1024 * 1024); // convert to MB/s | |
// Estimate time to upload larger files in minutes | |
let time1GB = (1024 / speed) / 60; | |
let time5GB = (5 * 1024 / speed) / 60; | |
let time10GB = (10 * 1024 / speed) / 60; | |
messageDiv.innerHTML = `All files uploaded successfully in ${elapsedTime.toFixed(2)} seconds, for all ${totalSize.toFixed(2)} MB in the ${files.length} files, speed ${speed.toFixed(2)} MB/s.<br>To upload a 1GB model at this speed, it would take approximately ${time1GB.toFixed(2)} minutes.<br>To upload a 5GB model at this speed, it would take approximately ${time5GB.toFixed(2)} minutes.<br>To upload a 10GB model at this speed, it would take approximately ${time10GB.toFixed(2)} minutes.`; | |
processingMessage.textContent = "All files processed"; | |
} else { | |
messageDiv.textContent = 'Please select files to upload'; | |
} | |
} | |
</script> | |
</body> | |
</html> |