multimodalart's picture
Update index.html
367dacb
<!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;
}
#drop_zone {
width: 300px;
height: 200px;
border: 2px dashed #aaa;
line-height: 200px;
text-align: center;
margin-top: 10px;
}
#file_list {
margin-top: 10px;
}
#fileUpload {
display: none;
}
</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">
<div id="drop_zone">Drag files/folders here or click to browse from your computer.</div>
<ul id="file_list"></ul>
<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.files = [];
this.totalUploaded = 0;
this.startTime = 0;
this.progressMap = new Map();
this.fileInput = document.getElementById('fileUpload');
this.dropZone = document.getElementById('drop_zone');
this.fileList = document.getElementById('file_list');
this.uploadButton = document.getElementById('uploadButton');
this.progressBar = document.getElementById('progressBar');
this.messageDiv = document.getElementById('message');
this.errorDiv = document.getElementById('error');
this.processingMessage = document.getElementById('processingMessage');
this.tokenInput = document.getElementById('tokenInput');
this.repoInput = document.getElementById('repoInput');
this.hijackFetch();
this.fileInput.addEventListener('change', (e) => this.handleFileSelect(e));
this.dropZone.addEventListener('click', () => this.fileInput.click());
this.dropZone.addEventListener('dragover', event => event.preventDefault());
this.dropZone.addEventListener('drop', (e) => this.handleFileDrop(e));
this.uploadButton.addEventListener('click', () => this.upload());
}
hijackFetch() {
const originalFetch = fetch;
fetch = (url, init) => {
if (init.method !== 'PUT') {
return originalFetch(url, init);
}
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]);
}
this.handleXHR(xhr, resolve, reject, url, init);
});
};
}
handleXHR(xhr, resolve, reject, url, init) {
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);
const elapsedSeconds = (Date.now() - this.startTime) / 1000;
this.progressBar.value = this.totalUploaded;
if (this.totalUploaded === 0) {
this.processingMessage.textContent = 'Preparing your upload';
} else if (this.totalUploaded === this.progressBar.max) {
this.processingMessage.textContent = 'Processing your upload';
}
}
}
handleFileSelect(event) {
const newFiles = Array.from(event.target.files).map(file => ({ path: file.name, content: file }));
this.files = this.files.concat(newFiles);
this.updateFileList();
}
handleFileDrop(event) {
event.preventDefault();
let items = event.dataTransfer.items;
for (let i = 0; i < items.length; i++) {
let item = items[i].webkitGetAsEntry();
if (item) {
this.traverseFileTree(item);
}
}
}
traverseFileTree(item, path = '') {
if (item.isFile) {
item.file((file) => {
this.files.push({ path: path + file.name, content: file });
this.updateFileList();
});
} else if (item.isDirectory) {
let dirReader = item.createReader();
dirReader.readEntries((entries) => {
for (let i = 0; i < entries.length; i++) {
this.traverseFileTree(entries[i], path + item.name + "/");
}
});
}
}
updateFileList() {
this.fileList.innerHTML = '';
for (let file of this.files) {
let listItem = document.createElement('li');
listItem.textContent = file.path;
this.fileList.appendChild(listItem);
}
}
async upload() {
this.progressBar.value = 0;
this.messageDiv.textContent = '';
this.errorDiv.textContent = '';
this.processingMessage.textContent = '';
const HF_ACCESS_TOKEN = this.tokenInput.value;
const REPO_ID = this.repoInput.value;
if (this.files.length > 0) {
this.prepareUpload();
try {
await this.createRepository(REPO_ID, HF_ACCESS_TOKEN);
await this.uploadFilesToRepo(REPO_ID, HF_ACCESS_TOKEN);
this.handleUploadSuccess();
} catch (error) {
this.handleErrorDuringUpload(error);
}
} else {
this.messageDiv.textContent = 'No files selected for upload.';
}
}
prepareUpload() {
let totalSize = this.files.reduce((total, file) => total + file.content.size, 0);
this.progressBar.max = totalSize;
this.totalUploaded = 0;
this.startTime = Date.now();
}
async createRepository(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;
}
}
}
async uploadFilesToRepo(REPO_ID, HF_ACCESS_TOKEN) {
await uploadFiles({
repo: REPO_ID,
credentials: { accessToken: HF_ACCESS_TOKEN },
files: this.files
});
}
handleUploadSuccess() {
this.messageDiv.textContent = 'Upload successful!';
this.processingMessage.textContent = '';
this.files = [];
this.updateFileList();
}
handleErrorDuringUpload(error) {
console.error('Error during upload', error);
this.errorDiv.textContent = 'Error during upload: ' + error.message;
}
}
new FileUploader();
</script>
</body>
</html>