File size: 7,483 Bytes
dc1be6e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78424dc
c13d23b
dc1be6e
c13d23b
 
dc1be6e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78424dc
dc1be6e
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
!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>