File size: 6,895 Bytes
9a25157
dc1be6e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2137dcd
dc1be6e
 
e45bb6a
dc1be6e
 
ccd8a2a
dc1be6e
 
ccd8a2a
dc1be6e
 
ccd8a2a
 
493c49f
93f9cae
493c49f
 
ccd8a2a
 
 
 
 
493c49f
 
 
ccd8a2a
3ce1c06
daa82b2
ccd8a2a
f366cad
3ce1c06
dc1be6e
 
3ce1c06
dc1be6e
ddc2532
dc1be6e
 
 
ddc2532
dc1be6e
f366cad
 
 
 
 
 
 
 
 
 
dc1be6e
f366cad
3ce1c06
dc1be6e
 
3ce1c06
dc1be6e
 
3ce1c06
 
daa82b2
49746af
 
 
 
daa82b2
 
 
e45bb6a
49746af
 
 
 
 
 
 
dc1be6e
 
49746af
daa82b2
3ce1c06
dc1be6e
78424dc
c13d23b
ccd8a2a
dc1be6e
c13d23b
ccd8a2a
 
3ce1c06
dc1be6e
 
b00a78e
dc1be6e
b00a78e
dc1be6e
b00a78e
dc1be6e
 
 
 
b00a78e
 
 
 
ccd8a2a
dc1be6e
b00a78e
 
 
 
493c49f
 
ccd8a2a
dc1be6e
ccd8a2a
dc1be6e
 
 
 
 
 
 
 
 
 
 
b00a78e
dc1be6e
 
ccd8a2a
dc1be6e
 
 
 
 
 
ccd8a2a
dc1be6e
493c49f
dc1be6e
 
 
b00a78e
dc1be6e
ccd8a2a
b00a78e
ad4aed3
 
ccd8a2a
dc1be6e
 
 
ad4aed3
00fe529
dc1be6e
 
 
 
78424dc
dc1be6e
 
493c49f
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<!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>
    <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/[email protected]/+esm";

      const uploadButton = document.getElementById('uploadButton');
      uploadButton.addEventListener('click', upload);

      function isS3Url(url) {
        // The condition to identify S3 URLs and other URLs to track
        return url.startsWith('https://s3.us-east-1.amazonaws/') ||
               url.includes('preupload/main') ||
               url.includes('commit/main');
      }

      // Save the original fetch function
      const originalFetch = fetch;

      // Create a variable to track the total uploaded size
      let totalUploaded = 0;

      // Replace the global fetch function
      let progressMap = new Map();
      
      fetch = (url, init) => {
        console.log(url, init)
        if (init.method === 'PUT') {
          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),
                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) => {
              if (event.lengthComputable) {
                progressMap.set(url, event.loaded);
                totalUploaded = Array.from(progressMap.values()).reduce((a, b) => a + b, 0);
            
                // Calculate speed
                const elapsedSeconds = (Date.now() - startTime) / 1000;
                const speedInMBps = totalUploaded / elapsedSeconds / 1024 / 1024;
              
                // Update progress bar and speed display
                const progressBar = document.getElementById('progressBar');
                progressBar.value = totalUploaded;
                
                // Update processing message
                const processingMessage = document.getElementById('processingMessage');
                if (totalUploaded === 0) {
                  processingMessage.textContent = 'Preparing your upload';
                } else if (totalUploaded === progressBar.max) {
                  processingMessage.textContent = 'Processing your upload';
                }
              }
            };


      
            xhr.send(init.body);
          });
        } else {
          // Use the original fetch function for non-S3 requests
          return originalFetch(url, init);
        }
      };


      async function upload() {
        const fileInput = document.getElementById('fileUpload');
        const files = Array.from(fileInput.files);
        const tokenInput = document.getElementById('tokenInput');
        const HF_ACCESS_TOKEN = tokenInput.value;
        const repoInput = document.getElementById('repoInput');
        const REPO_ID = repoInput.value;
        const progressBar = document.getElementById('progressBar');
        const messageDiv = document.getElementById('message');
        const errorDiv = document.getElementById('error');
        const processingMessage = document.getElementById('processingMessage');
        progressBar.value = 0;
        messageDiv.textContent = '';
        errorDiv.textContent = '';
        processingMessage.textContent = '';

        if (files.length > 0) {
          let totalSize = 0;
          for (let file of files) {
            totalSize += file.size;
          }
          progressBar.max = totalSize;  // Set the max value of progress bar
          totalUploaded = 0;  // Reset total uploaded size

          const startTime = Date.now();

          try {
            await createRepo({
              repo: REPO_ID,
              credentials: { accessToken: HF_ACCESS_TOKEN },
            });
          } catch (error) {
            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;
            }
          }

          try {
            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`);
            progressBar.value = totalSize;
          } catch (error) {
            console.error('Error uploading files', error);
            errorDiv.textContent = 'Error uploading files';
            return;
          }

          const elapsedTime = (Date.now() - startTime) / 1000;
          let totalSizeMB = totalSize / (1024 * 1024)
          let speed = totalSizeMB / elapsedTime;

          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 ${totalSizeMB.toFixed(2)} MB in the ${files.length} files, speed ${speed.toFixed(2)} MB/s.`;
          processingMessage.textContent = "All files processed";
        } else {
          messageDiv.textContent = 'Please select files to upload';
        }
      }
    </script>
  </body>
</html>