11import JSON5 from "json5" ;
22import env from "$/env.json" ;
33
4- /**
5- * Upload files to the server.
6- *
7- * @param state The state to apply the delta to.
8- * @param handler The handler to use.
9- * @param upload_id The upload id to use.
10- * @param on_upload_progress The function to call on upload progress.
11- * @param socket the websocket connection
12- * @param extra_headers Extra headers to send with the request.
13- * @param refs The refs object to store the abort controller in.
14- * @param getBackendURL Function to get the backend URL.
15- * @param getToken Function to get the Reflex token.
16- *
17- * @returns The response from posting to the UPLOADURL endpoint.
18- */
19- export const uploadFiles = async (
20- handler ,
21- files ,
22- upload_id ,
23- on_upload_progress ,
24- extra_headers ,
25- socket ,
26- refs ,
27- getBackendURL ,
28- getToken ,
29- ) => {
30- // return if there's no file to upload
31- if ( files === undefined || files . length === 0 ) {
32- return false ;
33- }
34-
35- const upload_ref_name = `__upload_controllers_${ upload_id } ` ;
36-
37- if ( refs [ upload_ref_name ] ) {
38- console . log ( "Upload already in progress for " , upload_id ) ;
39- return false ;
40- }
41-
4+ const trackUploadResponse = ( socket ) => {
425 // Track how many partial updates have been processed for this upload.
436 let resp_idx = 0 ;
44- const eventHandler = ( progressEvent ) => {
7+
8+ return ( progressEvent ) => {
459 const event_callbacks = socket . _callbacks . $event ;
4610 // Whenever called, responseText will contain the entire response so far.
4711 const chunks = progressEvent . event . target . responseText . trim ( ) . split ( "\n" ) ;
@@ -73,22 +37,32 @@ export const uploadFiles = async (
7337 }
7438 } ) ;
7539 } ;
40+ } ;
7641
77- const controller = new AbortController ( ) ;
78- const formdata = new FormData ( ) ;
42+ const sendUploadRequest = async ( {
43+ handler,
44+ upload_id,
45+ on_upload_progress,
46+ extra_headers,
47+ refs,
48+ getToken,
49+ formdata,
50+ url,
51+ responseHandler,
52+ } ) => {
53+ const upload_ref_name = `__upload_controllers_${ upload_id } ` ;
7954
80- // Add the token and handler to the file name.
81- files . forEach ( ( file ) => {
82- formdata . append ( "files" , file , file . path || file . name ) ;
83- } ) ;
55+ if ( refs [ upload_ref_name ] ) {
56+ return false ;
57+ }
58+
59+ const controller = new AbortController ( ) ;
8460
85- // Send the file to the server.
8661 refs [ upload_ref_name ] = controller ;
8762
8863 return new Promise ( ( resolve , reject ) => {
8964 const xhr = new XMLHttpRequest ( ) ;
9065
91- // Set up event handlers
9266 xhr . onload = function ( ) {
9367 if ( xhr . status >= 200 && xhr . status < 300 ) {
9468 resolve ( {
@@ -112,42 +86,36 @@ export const uploadFiles = async (
11286 reject ( new Error ( "Upload aborted" ) ) ;
11387 } ;
11488
115- // Handle upload progress
11689 if ( on_upload_progress ) {
11790 xhr . upload . onprogress = function ( event ) {
11891 if ( event . lengthComputable ) {
119- const progressEvent = {
92+ on_upload_progress ( {
12093 loaded : event . loaded ,
12194 total : event . total ,
12295 progress : event . loaded / event . total ,
123- } ;
124- on_upload_progress ( progressEvent ) ;
96+ } ) ;
12597 }
12698 } ;
12799 }
128100
129- // Handle download progress with streaming response parsing
130- xhr . onprogress = function ( event ) {
131- if ( eventHandler ) {
132- const progressEvent = {
101+ if ( responseHandler ) {
102+ xhr . onprogress = function ( event ) {
103+ responseHandler ( {
133104 event : {
134105 target : {
135106 responseText : xhr . responseText ,
136107 } ,
137108 } ,
138109 progress : event . lengthComputable ? event . loaded / event . total : 0 ,
139- } ;
140- eventHandler ( progressEvent ) ;
141- }
142- } ;
110+ } ) ;
111+ } ;
112+ }
143113
144- // Handle abort controller
145114 controller . signal . addEventListener ( "abort" , ( ) => {
146115 xhr . abort ( ) ;
147116 } ) ;
148117
149- // Configure and send request
150- xhr . open ( "POST" , getBackendURL ( env . UPLOAD ) ) ;
118+ xhr . open ( "POST" , url ) ;
151119 xhr . setRequestHeader ( "Reflex-Client-Token" , getToken ( ) ) ;
152120 xhr . setRequestHeader ( "Reflex-Event-Handler" , handler ) ;
153121 for ( const [ key , value ] of Object . entries ( extra_headers || { } ) ) {
@@ -168,3 +136,99 @@ export const uploadFiles = async (
168136 delete refs [ upload_ref_name ] ;
169137 } ) ;
170138} ;
139+
140+ /**
141+ * Upload files to the server.
142+ *
143+ * @param handler The handler to use.
144+ * @param upload_id The upload id to use.
145+ * @param on_upload_progress The function to call on upload progress.
146+ * @param extra_headers Extra headers to send with the request.
147+ * @param socket The websocket connection.
148+ * @param refs The refs object to store the abort controller in.
149+ * @param getBackendURL Function to get the backend URL.
150+ * @param getToken Function to get the Reflex token.
151+ *
152+ * @returns The response from posting to the upload endpoint.
153+ */
154+ export const uploadFiles = async (
155+ handler ,
156+ files ,
157+ upload_id ,
158+ on_upload_progress ,
159+ extra_headers ,
160+ socket ,
161+ refs ,
162+ getBackendURL ,
163+ getToken ,
164+ ) => {
165+ if ( files === undefined || files . length === 0 ) {
166+ return false ;
167+ }
168+
169+ const formdata = new FormData ( ) ;
170+
171+ files . forEach ( ( file ) => {
172+ formdata . append ( "files" , file , file . path || file . name ) ;
173+ } ) ;
174+
175+ return sendUploadRequest ( {
176+ handler,
177+ upload_id,
178+ on_upload_progress,
179+ extra_headers,
180+ refs,
181+ getToken,
182+ formdata,
183+ url : getBackendURL ( env . UPLOAD ) ,
184+ responseHandler : trackUploadResponse ( socket ) ,
185+ } ) ;
186+ } ;
187+
188+ /**
189+ * Upload files to the streaming chunk endpoint.
190+ *
191+ * @param handler The handler to use.
192+ * @param files The files to upload.
193+ * @param upload_id The upload id to use.
194+ * @param on_upload_progress The function to call on upload progress.
195+ * @param extra_headers Extra headers to send with the request.
196+ * @param _socket The websocket connection.
197+ * @param refs The refs object to store the abort controller in.
198+ * @param getBackendURL Function to get the backend URL.
199+ * @param getToken Function to get the Reflex token.
200+ *
201+ * @returns The response from posting to the chunk upload endpoint.
202+ */
203+ export const uploadFilesChunk = async (
204+ handler ,
205+ files ,
206+ upload_id ,
207+ on_upload_progress ,
208+ extra_headers ,
209+ _socket ,
210+ refs ,
211+ getBackendURL ,
212+ getToken ,
213+ ) => {
214+ if ( files === undefined || files . length === 0 ) {
215+ return false ;
216+ }
217+
218+ const formdata = new FormData ( ) ;
219+
220+ files . forEach ( ( file ) => {
221+ formdata . append ( "files" , file , file . path || file . name ) ;
222+ } ) ;
223+
224+ return sendUploadRequest ( {
225+ handler,
226+ upload_id,
227+ on_upload_progress,
228+ extra_headers,
229+ refs,
230+ getToken,
231+ formdata,
232+ url : getBackendURL ( env . UPLOAD_CHUNK ) ,
233+ } ) ;
234+ } ;
0 commit comments