triflix commited on
Commit
06fbe5b
·
verified ·
1 Parent(s): ed95574

Update app/static/script.js

Browse files
Files changed (1) hide show
  1. app/static/script.js +51 -92
app/static/script.js CHANGED
@@ -1,17 +1,13 @@
1
  // app/static/script.js
2
  document.addEventListener('DOMContentLoaded', () => {
3
- // --- Constants and State ---
4
- const CHUNK_SIZE = 4 * 1024 * 1024; // 4MB chunks
5
  let currentFile = null;
6
- let session = {}; // To hold session_id and token
7
- let websocket = null;
8
 
9
  // --- DOM Elements ---
10
- const uploaderCard = document.getElementById('uploader-card');
11
  const states = {
12
  initial: document.getElementById('state-initial'),
13
  uploading: document.getElementById('state-uploading'),
14
- assembling: document.getElementById('state-assembling'),
15
  complete: document.getElementById('state-complete'),
16
  error: document.getElementById('state-error'),
17
  };
@@ -39,7 +35,6 @@ document.addEventListener('DOMContentLoaded', () => {
39
  browseBtn.addEventListener('click', () => fileInput.click());
40
  fileInput.addEventListener('change', handleFileSelect);
41
 
42
- // Drag and Drop
43
  dropZone.addEventListener('dragover', (e) => {
44
  e.preventDefault();
45
  dropZone.classList.add('drag-over');
@@ -48,16 +43,14 @@ document.addEventListener('DOMContentLoaded', () => {
48
  dropZone.addEventListener('drop', (e) => {
49
  e.preventDefault();
50
  dropZone.classList.remove('drag-over');
51
- const files = e.dataTransfer.files;
52
- if (files.length > 0) {
53
- handleFileSelect({ target: { files: files } });
54
  }
55
  });
56
 
57
  uploadAnotherBtn.addEventListener('click', resetUploader);
58
  retryBtn.addEventListener('click', resetUploader);
59
 
60
-
61
  // --- Core Functions ---
62
  function handleFileSelect(event) {
63
  const file = event.target.files[0];
@@ -67,104 +60,70 @@ document.addEventListener('DOMContentLoaded', () => {
67
  fileNameEl.textContent = file.name;
68
  fileSizeEl.textContent = formatBytes(file.size);
69
 
70
- startUploadProcess(file);
71
  }
72
 
73
- async function startUploadProcess(file) {
74
  switchState('uploading');
75
- statusText.textContent = 'Creating secure session...';
76
  progressBar.style.width = '0%';
77
 
78
- try {
79
- // 1. Create a new session
80
- const response = await fetch('/sessions', { method: 'POST' });
81
- if (!response.ok) throw new Error('Failed to create session.');
82
- session = await response.json();
83
-
84
- // 2. Setup WebSocket for progress
85
- setupWebSocket();
86
-
87
- // 3. Start uploading chunks
88
- await uploadFileInChunks(file);
89
-
90
- // 4. Finalize the upload
91
- statusText.textContent = 'Finalizing upload...';
92
- const completeResponse = await fetch(`/complete/${session.session_id}`, { method: 'POST' });
93
- if (!completeResponse.ok) throw new Error('Failed to finalize upload.');
94
-
95
- const result = await completeResponse.json();
96
- downloadLink.href = result.download_url;
97
-
98
- } catch (error) {
99
- console.error('Upload process failed:', error);
100
- showError(error.message);
101
- }
102
- }
103
-
104
- function setupWebSocket() {
105
- const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
106
- const wsUrl = `${wsProtocol}//${window.location.host}/ws/${session.session_id}`;
107
- websocket = new WebSocket(wsUrl);
108
-
109
- websocket.onmessage = (event) => {
110
- const data = JSON.parse(event.data);
111
- if (data.type === 'progress') {
112
- updateProgress(data.uploaded_bytes, data.total_bytes);
113
- if(data.status === 'assembling') {
114
- switchState('assembling');
115
- } else if(data.status === 'completed') {
116
- switchState('complete');
117
- }
118
  }
119
- };
120
- websocket.onerror = (error) => console.error('WebSocket Error:', error);
121
- websocket.onclose = () => console.log('WebSocket closed.');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  }
123
 
124
- async function uploadFileInChunks(file) {
125
- const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
126
- for (let i = 0; i < totalChunks; i++) {
127
- const start = i * CHUNK_SIZE;
128
- const end = Math.min(start + CHUNK_SIZE, file.size);
129
- const chunk = file.slice(start, end);
130
-
131
- const formData = new FormData();
132
- formData.append('file', chunk, file.name);
133
-
134
- const url = `/upload/${session.session_id}?chunk_index=${i}&total_size=${file.size}`;
135
-
136
- statusText.textContent = `Uploading chunk ${i + 1} of ${totalChunks}...`;
137
-
138
- const response = await fetch(url, {
139
- method: 'PUT',
140
- body: formData,
141
- });
142
-
143
- if (!response.ok) {
144
- const errorData = await response.json();
145
- throw new Error(errorData.detail || 'Chunk upload failed.');
146
  }
147
  }
148
- }
149
-
150
- function updateProgress(uploaded, total) {
151
- if (total > 0) {
152
- const percentage = (uploaded / total) * 100;
153
- progressBar.style.width = `${percentage}%`;
154
- statusText.textContent = `${formatBytes(uploaded)} / ${formatBytes(total)}`;
155
- }
156
- }
157
-
158
- function showError(message) {
159
  errorMessage.textContent = message;
160
  switchState('error');
161
  }
162
 
163
  function resetUploader() {
 
 
 
 
164
  currentFile = null;
165
- session = {};
166
  fileInput.value = ''; // Reset file input
167
- if (websocket) websocket.close();
168
  switchState('initial');
169
  }
170
 
 
1
  // app/static/script.js
2
  document.addEventListener('DOMContentLoaded', () => {
3
+ // --- State ---
 
4
  let currentFile = null;
5
+ let currentXHR = null; // To hold the request object for cancellation
 
6
 
7
  // --- DOM Elements ---
 
8
  const states = {
9
  initial: document.getElementById('state-initial'),
10
  uploading: document.getElementById('state-uploading'),
 
11
  complete: document.getElementById('state-complete'),
12
  error: document.getElementById('state-error'),
13
  };
 
35
  browseBtn.addEventListener('click', () => fileInput.click());
36
  fileInput.addEventListener('change', handleFileSelect);
37
 
 
38
  dropZone.addEventListener('dragover', (e) => {
39
  e.preventDefault();
40
  dropZone.classList.add('drag-over');
 
43
  dropZone.addEventListener('drop', (e) => {
44
  e.preventDefault();
45
  dropZone.classList.remove('drag-over');
46
+ if (e.dataTransfer.files.length > 0) {
47
+ handleFileSelect({ target: { files: e.dataTransfer.files } });
 
48
  }
49
  });
50
 
51
  uploadAnotherBtn.addEventListener('click', resetUploader);
52
  retryBtn.addEventListener('click', resetUploader);
53
 
 
54
  // --- Core Functions ---
55
  function handleFileSelect(event) {
56
  const file = event.target.files[0];
 
60
  fileNameEl.textContent = file.name;
61
  fileSizeEl.textContent = formatBytes(file.size);
62
 
63
+ startUpload(file);
64
  }
65
 
66
+ function startUpload(file) {
67
  switchState('uploading');
68
+ statusText.textContent = 'Uploading...';
69
  progressBar.style.width = '0%';
70
 
71
+ const formData = new FormData();
72
+ formData.append('file', file);
73
+
74
+ // We use XMLHttpRequest instead of fetch because it provides
75
+ // a native 'onprogress' event for tracking upload progress.
76
+ const xhr = new XMLHttpRequest();
77
+ currentXHR = xhr;
78
+
79
+ xhr.upload.addEventListener('progress', (event) => {
80
+ if (event.lengthComputable) {
81
+ const percentage = (event.loaded / event.total) * 100;
82
+ progressBar.style.width = `${percentage}%`;
83
+ statusText.textContent = `${formatBytes(event.loaded)} / ${formatBytes(event.total)}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
85
+ });
86
+
87
+ xhr.addEventListener('load', () => {
88
+ if (xhr.status >= 200 && xhr.status < 300) {
89
+ const response = JSON.parse(xhr.responseText);
90
+ downloadLink.href = response.download_url;
91
+ downloadLink.download = response.filename; // Set the default download filename
92
+ switchState('complete');
93
+ } else {
94
+ handleUploadError(xhr);
95
+ }
96
+ });
97
+
98
+ xhr.addEventListener('error', () => handleUploadError(xhr));
99
+ xhr.addEventListener('abort', () => console.log('Upload aborted.'));
100
+
101
+ xhr.open('POST', '/upload', true);
102
+ xhr.send(formData);
103
  }
104
 
105
+ function handleUploadError(xhr) {
106
+ let message = 'An unknown network error occurred.';
107
+ try {
108
+ const errorData = JSON.parse(xhr.responseText);
109
+ message = errorData.detail || 'Upload failed.';
110
+ } catch (e) {
111
+ // Response was not JSON, use status text
112
+ if (xhr.statusText) {
113
+ message = xhr.statusText;
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
115
  }
 
 
 
 
 
 
 
 
 
 
 
116
  errorMessage.textContent = message;
117
  switchState('error');
118
  }
119
 
120
  function resetUploader() {
121
+ if (currentXHR) {
122
+ currentXHR.abort(); // Cancel any ongoing upload
123
+ currentXHR = null;
124
+ }
125
  currentFile = null;
 
126
  fileInput.value = ''; // Reset file input
 
127
  switchState('initial');
128
  }
129