coollsd commited on
Commit
8ea5abe
1 Parent(s): 8025976

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -50
app.py CHANGED
@@ -2,7 +2,7 @@ from fastapi import FastAPI, File, UploadFile, Request
2
  from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
3
  import requests
4
  import time
5
- from typing import Dict
6
 
7
  app = FastAPI()
8
 
@@ -24,6 +24,22 @@ HTML_CONTENT = """
24
  justify-content: center;
25
  align-items: center;
26
  color: #e0e0e0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  }
28
  .container {
29
  background: rgba(255, 255, 255, 0.1);
@@ -38,11 +54,12 @@ HTML_CONTENT = """
38
  transition: all 0.3s ease;
39
  }
40
  .container:hover {
 
41
  transform: translateY(-5px);
42
  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
43
  }
44
  h1 {
45
- color: #00CED1;
46
  margin-bottom: 1.5rem;
47
  font-weight: 600;
48
  }
@@ -50,7 +67,7 @@ HTML_CONTENT = """
50
  display: none;
51
  }
52
  .btn {
53
- background-color: #00CED1;
54
  color: #121212;
55
  padding: 12px 24px;
56
  border-radius: 5px;
@@ -71,7 +88,7 @@ HTML_CONTENT = """
71
  left: 50%;
72
  width: 5px;
73
  height: 5px;
74
- background: rgba(255, 255, 255, 0.5);
75
  opacity: 0;
76
  border-radius: 100%;
77
  transform: scale(1, 1) translate(-50%);
@@ -95,7 +112,7 @@ HTML_CONTENT = """
95
  animation: ripple 1s ease-out;
96
  }
97
  .btn:hover {
98
- background-color: #00A9A9;
99
  }
100
  .btn:disabled {
101
  background-color: #555;
@@ -116,11 +133,12 @@ HTML_CONTENT = """
116
  background-color: #333;
117
  border-radius: 5px;
118
  overflow: hidden;
 
119
  }
120
  .progress {
121
  width: 0%;
122
  height: 100%;
123
- background-color: #00CED1;
124
  transition: width 0.3s ease;
125
  }
126
  .loading-spinner {
@@ -128,7 +146,7 @@ HTML_CONTENT = """
128
  width: 40px;
129
  height: 40px;
130
  border: 4px solid #333;
131
- border-top: 4px solid #00CED1;
132
  border-radius: 50%;
133
  animation: spin 1s linear infinite;
134
  margin: 20px auto;
@@ -142,14 +160,13 @@ HTML_CONTENT = """
142
  margin-top: 1.5rem;
143
  }
144
  .result-link {
145
- color: #00CED1;
146
  text-decoration: none;
147
  font-weight: 600;
148
  transition: all 0.3s ease;
149
  margin-right: 10px;
150
  }
151
  .result-link:hover {
152
- color: #00A9A9;
153
  text-decoration: underline;
154
  }
155
  .copy-btn {
@@ -167,91 +184,123 @@ HTML_CONTENT = """
167
  </style>
168
  </head>
169
  <body>
 
170
  <div class="container">
171
  <h1>Pro File Uploader</h1>
172
  <form id="uploadForm">
173
- <input type="file" name="file" id="file" class="file-input" accept="*/*" required>
174
- <label for="file" class="btn">Choose File</label>
175
  <div class="file-name" id="fileName"></div>
176
- <button type="button" id="uploadBtn" class="btn" style="display: none; margin-top: 1rem;">Upload File</button>
177
- <div class="progress-container" id="progressContainer">
178
- <div class="progress-bar">
179
- <div class="progress" id="progress"></div>
180
- </div>
181
- </div>
182
  <div class="loading-spinner" id="loadingSpinner"></div>
183
  </form>
184
- <div class="result-container" id="resultContainer">
185
- <a href="#" class="result-link" id="resultLink" target="_blank">View Uploaded File</a>
186
- <button class="copy-btn" id="copyBtn">Copy Link</button>
187
- </div>
188
  </div>
189
 
190
  <script>
191
- const fileInput = document.getElementById('file');
192
  const fileName = document.getElementById('fileName');
193
  const uploadBtn = document.getElementById('uploadBtn');
194
  const progressContainer = document.getElementById('progressContainer');
195
- const progress = document.getElementById('progress');
196
  const loadingSpinner = document.getElementById('loadingSpinner');
197
  const resultContainer = document.getElementById('resultContainer');
198
- const resultLink = document.getElementById('resultLink');
199
- const copyBtn = document.getElementById('copyBtn');
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
  fileInput.addEventListener('change', (e) => {
202
  if (e.target.files.length > 0) {
203
- fileName.textContent = e.target.files[0].name;
 
204
  uploadBtn.style.display = 'inline-block';
205
  }
206
  });
207
 
208
  uploadBtn.addEventListener('click', () => {
209
  if (fileInput.files.length > 0) {
210
- uploadFile(fileInput.files[0]);
211
  }
212
  });
213
 
214
- function uploadFile(file) {
215
- const formData = new FormData();
216
- formData.append('file', file);
217
-
218
  progressContainer.style.display = 'block';
219
  loadingSpinner.style.display = 'block';
220
  uploadBtn.disabled = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
 
222
  const xhr = new XMLHttpRequest();
223
  xhr.open('POST', '/upload', true);
224
- xhr.upload.onprogress = updateProgress;
225
  xhr.onload = function() {
226
- loadingSpinner.style.display = 'none';
227
- uploadBtn.disabled = false;
228
  if (xhr.status === 200) {
229
  const response = JSON.parse(xhr.responseText);
230
  if (response.url) {
231
- resultLink.href = response.url;
232
- resultLink.textContent = 'View Uploaded File';
233
- resultContainer.style.display = 'block';
234
  } else {
235
  alert('Upload failed: ' + response.error);
236
  }
237
  } else {
238
  alert('Upload failed: ' + xhr.statusText);
239
  }
240
- resetUploadState();
 
 
241
  };
242
  xhr.onerror = function() {
243
- loadingSpinner.style.display = 'none';
244
- uploadBtn.disabled = false;
245
  alert('Upload failed: Network error');
246
- resetUploadState();
 
 
247
  };
248
  xhr.send(formData);
249
  }
250
 
251
- function updateProgress(event) {
252
  if (event.lengthComputable) {
253
  const percentComplete = (event.loaded / event.total) * 100;
254
- progress.style.width = percentComplete + '%';
255
  }
256
  }
257
 
@@ -259,15 +308,45 @@ HTML_CONTENT = """
259
  fileInput.value = '';
260
  fileName.textContent = '';
261
  uploadBtn.style.display = 'none';
262
- progressContainer.style.display = 'none';
263
- progress.style.width = '0%';
264
  }
265
 
266
- copyBtn.addEventListener('click', () => {
267
- navigator.clipboard.writeText(resultLink.href).then(() => {
268
- alert('Link copied to clipboard!');
269
- });
270
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  </script>
272
  </body>
273
  </html>
 
2
  from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse
3
  import requests
4
  import time
5
+ from typing import Dict, List
6
 
7
  app = FastAPI()
8
 
 
24
  justify-content: center;
25
  align-items: center;
26
  color: #e0e0e0;
27
+ overflow: hidden;
28
+ }
29
+ .background {
30
+ position: fixed;
31
+ top: 0;
32
+ left: 0;
33
+ right: 0;
34
+ bottom: 0;
35
+ z-index: -1;
36
+ }
37
+ .dot {
38
+ position: absolute;
39
+ width: 2px;
40
+ height: 2px;
41
+ background: rgba(255, 255, 255, 0.3);
42
+ border-radius: 50%;
43
  }
44
  .container {
45
  background: rgba(255, 255, 255, 0.1);
 
54
  transition: all 0.3s ease;
55
  }
56
  .container:hover {
57
+ background: rgba(255, 255, 255, 0.2);
58
  transform: translateY(-5px);
59
  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3);
60
  }
61
  h1 {
62
+ color: #ffffff;
63
  margin-bottom: 1.5rem;
64
  font-weight: 600;
65
  }
 
67
  display: none;
68
  }
69
  .btn {
70
+ background-color: #ffffff;
71
  color: #121212;
72
  padding: 12px 24px;
73
  border-radius: 5px;
 
88
  left: 50%;
89
  width: 5px;
90
  height: 5px;
91
+ background: rgba(0, 0, 0, 0.3);
92
  opacity: 0;
93
  border-radius: 100%;
94
  transform: scale(1, 1) translate(-50%);
 
112
  animation: ripple 1s ease-out;
113
  }
114
  .btn:hover {
115
+ background-color: #f0f0f0;
116
  }
117
  .btn:disabled {
118
  background-color: #555;
 
133
  background-color: #333;
134
  border-radius: 5px;
135
  overflow: hidden;
136
+ margin-bottom: 10px;
137
  }
138
  .progress {
139
  width: 0%;
140
  height: 100%;
141
+ background-color: #ffffff;
142
  transition: width 0.3s ease;
143
  }
144
  .loading-spinner {
 
146
  width: 40px;
147
  height: 40px;
148
  border: 4px solid #333;
149
+ border-top: 4px solid #ffffff;
150
  border-radius: 50%;
151
  animation: spin 1s linear infinite;
152
  margin: 20px auto;
 
160
  margin-top: 1.5rem;
161
  }
162
  .result-link {
163
+ color: #ffffff;
164
  text-decoration: none;
165
  font-weight: 600;
166
  transition: all 0.3s ease;
167
  margin-right: 10px;
168
  }
169
  .result-link:hover {
 
170
  text-decoration: underline;
171
  }
172
  .copy-btn {
 
184
  </style>
185
  </head>
186
  <body>
187
+ <div class="background" id="background"></div>
188
  <div class="container">
189
  <h1>Pro File Uploader</h1>
190
  <form id="uploadForm">
191
+ <input type="file" name="files" id="files" class="file-input" accept="*/*" required multiple>
192
+ <label for="files" class="btn">Choose Files</label>
193
  <div class="file-name" id="fileName"></div>
194
+ <button type="button" id="uploadBtn" class="btn" style="display: none; margin-top: 1rem;">Upload Files</button>
195
+ <div class="progress-container" id="progressContainer"></div>
 
 
 
 
196
  <div class="loading-spinner" id="loadingSpinner"></div>
197
  </form>
198
+ <div class="result-container" id="resultContainer"></div>
 
 
 
199
  </div>
200
 
201
  <script>
202
+ const fileInput = document.getElementById('files');
203
  const fileName = document.getElementById('fileName');
204
  const uploadBtn = document.getElementById('uploadBtn');
205
  const progressContainer = document.getElementById('progressContainer');
 
206
  const loadingSpinner = document.getElementById('loadingSpinner');
207
  const resultContainer = document.getElementById('resultContainer');
208
+
209
+ function createBackground() {
210
+ const background = document.getElementById('background');
211
+ for (let i = 0; i < 50; i++) {
212
+ const dot = document.createElement('div');
213
+ dot.className = 'dot';
214
+ dot.style.left = `${Math.random() * 100}%`;
215
+ dot.style.top = `${Math.random() * 100}%`;
216
+ dot.style.animationDuration = `${Math.random() * 3 + 2}s`;
217
+ dot.style.animationDelay = `${Math.random() * 2}s`;
218
+ background.appendChild(dot);
219
+ }
220
+ }
221
+
222
+ createBackground();
223
 
224
  fileInput.addEventListener('change', (e) => {
225
  if (e.target.files.length > 0) {
226
+ const fileNames = Array.from(e.target.files).map(file => file.name).join(', ');
227
+ fileName.textContent = fileNames;
228
  uploadBtn.style.display = 'inline-block';
229
  }
230
  });
231
 
232
  uploadBtn.addEventListener('click', () => {
233
  if (fileInput.files.length > 0) {
234
+ uploadFiles(fileInput.files);
235
  }
236
  });
237
 
238
+ function uploadFiles(files) {
239
+ progressContainer.innerHTML = '';
 
 
240
  progressContainer.style.display = 'block';
241
  loadingSpinner.style.display = 'block';
242
  uploadBtn.disabled = true;
243
+ resultContainer.innerHTML = '';
244
+ resultContainer.style.display = 'none';
245
+
246
+ Array.from(files).forEach((file, index) => {
247
+ const progressBar = createProgressBar(file.name);
248
+ progressContainer.appendChild(progressBar);
249
+ uploadFile(file, progressBar, index);
250
+ });
251
+ }
252
+
253
+ function createProgressBar(fileName) {
254
+ const progressBarContainer = document.createElement('div');
255
+ progressBarContainer.className = 'progress-bar';
256
+ const progress = document.createElement('div');
257
+ progress.className = 'progress';
258
+ progressBarContainer.appendChild(progress);
259
+ const label = document.createElement('div');
260
+ label.textContent = fileName;
261
+ label.style.fontSize = '0.8rem';
262
+ label.style.marginBottom = '5px';
263
+ const container = document.createElement('div');
264
+ container.appendChild(label);
265
+ container.appendChild(progressBarContainer);
266
+ return container;
267
+ }
268
+
269
+ function uploadFile(file, progressBarContainer, index) {
270
+ const formData = new FormData();
271
+ formData.append('file', file);
272
 
273
  const xhr = new XMLHttpRequest();
274
  xhr.open('POST', '/upload', true);
275
+ xhr.upload.onprogress = (event) => updateProgress(event, progressBarContainer.querySelector('.progress'));
276
  xhr.onload = function() {
 
 
277
  if (xhr.status === 200) {
278
  const response = JSON.parse(xhr.responseText);
279
  if (response.url) {
280
+ addResultLink(response.url, file.name);
 
 
281
  } else {
282
  alert('Upload failed: ' + response.error);
283
  }
284
  } else {
285
  alert('Upload failed: ' + xhr.statusText);
286
  }
287
+ if (index === fileInput.files.length - 1) {
288
+ resetUploadState();
289
+ }
290
  };
291
  xhr.onerror = function() {
 
 
292
  alert('Upload failed: Network error');
293
+ if (index === fileInput.files.length - 1) {
294
+ resetUploadState();
295
+ }
296
  };
297
  xhr.send(formData);
298
  }
299
 
300
+ function updateProgress(event, progressBar) {
301
  if (event.lengthComputable) {
302
  const percentComplete = (event.loaded / event.total) * 100;
303
+ progressBar.style.width = percentComplete + '%';
304
  }
305
  }
306
 
 
308
  fileInput.value = '';
309
  fileName.textContent = '';
310
  uploadBtn.style.display = 'none';
311
+ uploadBtn.disabled = false;
312
+ loadingSpinner.style.display = 'none';
313
  }
314
 
315
+ function addResultLink(url, fileName) {
316
+ const linkContainer = document.createElement('div');
317
+ linkContainer.style.marginBottom = '10px';
318
+
319
+ const link = document.createElement('a');
320
+ link.href = url;
321
+ link.textContent = `View ${fileName}`;
322
+ link.className = 'result-link';
323
+ link.target = '_blank';
324
+
325
+ const copyBtn = document.createElement('button');
326
+ copyBtn.textContent = 'Copy Link';
327
+ copyBtn.className = 'copy-btn';
328
+ copyBtn.onclick = () => {
329
+ navigator.clipboard.writeText(url).then(() => {
330
+ alert('Link copied to clipboard!');
331
+ });
332
+ };
333
+
334
+ linkContainer.appendChild(link);
335
+ linkContainer.appendChild(copyBtn);
336
+ resultContainer.appendChild(linkContainer);
337
+ resultContainer.style.display = 'block';
338
+ }
339
+
340
+ // Background animation
341
+ const background = document.getElementById('background');
342
+ function animateDots() {
343
+ const dots = background.getElementsByClassName('dot');
344
+ for (let dot of dots) {
345
+ dot.style.transform = `translateY(-100vh)`;
346
+ }
347
+ }
348
+ setInterval(animateDots, 5000);
349
+ animateDots();
350
  </script>
351
  </body>
352
  </html>