Spaces:
Running
Running
<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> | |
<progress id="progressBar" value="0" max="100"></progress> | |
<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"; | |
class FileUploader { | |
constructor() { | |
this.fileInput = document.getElementById('fileUpload'); | |
this.uploadButton = document.getElementById('uploadButton'); | |
this.tokenInput = document.getElementById('tokenInput'); | |
this.repoInput = document.getElementById('repoInput'); | |
this.progressBar = document.getElementById('progressBar'); | |
this.messageDiv = document.getElementById('message'); | |
this.errorDiv = document.getElementById('error'); | |
this.processingMessage = document.getElementById('processingMessage'); | |
this.hijackFetch(); | |
this.uploadButton.addEventListener('click', this.upload); | |
} | |
hijackFetch = () => { | |
const originalFetch = fetch; | |
this.totalUploaded = 0; | |
this.progressMap = new Map(); | |
fetch = (url, init) => init.method !== 'PUT' ? originalFetch(url, init) : this.handleFetch(url, init); | |
}; | |
handleFetch = (url, init) => 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), json: () => Promise.resolve(JSON.parse(xhr.responseText)), headers: {get: (header) => xhr.getResponseHeader(header)}}); | |
xhr.onerror = () => reject(new TypeError('Network request failed')); | |
xhr.ontimeout = () => reject(new TypeError('Network request failed due to timeout')); | |
xhr.upload.onprogress = (event) => this.updateUploadProgress(event, url); | |
xhr.send(init.body); | |
}); | |
updateUploadProgress = (event, url) => { | |
if (event.lengthComputable) { | |
this.progressMap.set(url, event.loaded); | |
this.totalUploaded = Array.from(this.progressMap.values()).reduce((a, b) => a + b, 0); | |
this.progressBar.value = this.totalUploaded; | |
this.processingMessage.textContent = this.totalUploaded === 0 ? 'Preparing your upload' : this.totalUploaded === this.progressBar.max ? 'Processing your upload' : ''; | |
} | |
}; | |
upload = async () => { | |
const files = Array.from(this.fileInput.files); | |
const HF_ACCESS_TOKEN = this.tokenInput.value; | |
const REPO_ID = this.repoInput.value; | |
this.progressBar.value = 0; | |
this.messageDiv.textContent = ''; | |
this.errorDiv.textContent = ''; | |
this.processingMessage.textContent = ''; | |
if (files.length > 0) { | |
this.progressBar.max = files.reduce((total, file) => total + file.size, 0); | |
this.totalUploaded = 0; | |
this.startTime = Date.now(); | |
try { | |
await this.createRepository(REPO_ID, HF_ACCESS_TOKEN); | |
await this.uploadFilesToRepo(REPO_ID, HF_ACCESS_TOKEN, files); | |
this.handleUploadSuccess(files); | |
} catch (error) { | |
this.handleErrorDuringUpload(error); | |
} | |
} else { | |
this.messageDiv.textContent = 'Please select files to upload'; | |
} | |
}; | |
createRepository = async (REPO_ID, HF_ACCESS_TOKEN) => { | |
try { | |
await createRepo({repo: REPO_ID, credentials: { accessToken: HF_ACCESS_TOKEN }}); | |
} catch (error) { | |
if (error.message !== 'You already created this model repo') throw error; | |
} | |
}; | |
uploadFilesToRepo = (REPO_ID, HF_ACCESS_TOKEN, files) => uploadFiles({repo: REPO_ID, credentials: { accessToken: HF_ACCESS_TOKEN }, files: files.map(file => ({path: file.name, content: file}))}); | |
handleUploadSuccess = (files) => { | |
const elapsedTime = (Date.now() - this.startTime) / 1000; | |
let totalSizeMB = this.progressBar.max / (1024 * 1024) | |
let speed = totalSizeMB / elapsedTime; | |
this.messageDiv.innerHTML = `All files uploaded successfully in ${elapsedTime.toFixed(2)} seconds, for all ${totalSizeMB.toFixed(2)} MB in the ${files.length} files, speed ${speed.toFixed(2)} MB/s.`; | |
this.processingMessage.textContent = "All files processed"; | |
}; | |
handleErrorDuringUpload = (error) => { | |
console.error('Error during upload', error); | |
this.errorDiv.textContent = 'Error during upload: ' + error.message; | |
}; | |
} | |
new FileUploader(); | |
</script> | |
</body> | |
</html> | |