11const WORKER_URL = import . meta. env . VITE_WORKER_URL || ''
2+ const CHUNK_SIZE = 80 * 1024 * 1024 // 80MB per chunk (under CF 100MB limit)
23
34interface UploadResult {
45 id : string
@@ -9,30 +10,53 @@ export async function uploadVideo(
910 file : File ,
1011 onProgress : ( progress : number ) => void
1112) : Promise < UploadResult > {
12- // Start with indeterminate progress since Cloudflare buffers uploads
13- onProgress ( - 1 )
13+ // Step 1: Initialize upload
14+ const initRes = await fetch ( `${ WORKER_URL } /upload/init` , {
15+ method : 'POST' ,
16+ headers : { 'Content-Type' : 'application/json' } ,
17+ body : JSON . stringify ( {
18+ filename : file . name ,
19+ contentType : file . type || 'video/mp4' ,
20+ size : file . size ,
21+ } ) ,
22+ } )
23+
24+ if ( ! initRes . ok ) {
25+ const err = await initRes . json ( ) . catch ( ( ) => ( { error : 'Upload init failed' } ) )
26+ throw new Error ( ( err as { error : string } ) . error || `Init failed (${ initRes . status } )` )
27+ }
28+
29+ const { id, totalChunks } = await initRes . json ( ) as { id : string ; totalChunks : number }
30+
31+ // Step 2: Upload chunks
32+ for ( let i = 0 ; i < totalChunks ; i ++ ) {
33+ const start = i * CHUNK_SIZE
34+ const end = Math . min ( start + CHUNK_SIZE , file . size )
35+ const chunk = file . slice ( start , end )
36+
37+ const res = await fetch ( `${ WORKER_URL } /upload/${ id } /chunk/${ i } ` , {
38+ method : 'PUT' ,
39+ headers : { 'Content-Type' : 'application/octet-stream' } ,
40+ body : chunk ,
41+ } )
42+
43+ if ( ! res . ok ) {
44+ throw new Error ( `Chunk ${ i + 1 } /${ totalChunks } failed (${ res . status } )` )
45+ }
46+
47+ onProgress ( Math . round ( ( ( i + 1 ) / totalChunks ) * 100 ) )
48+ }
1449
15- const response = await fetch ( `${ WORKER_URL } /upload` , {
50+ // Step 3: Finalize
51+ const finalRes = await fetch ( `${ WORKER_URL } /upload/${ id } /finalize` , {
1652 method : 'POST' ,
17- headers : {
18- 'Content-Type' : file . type || 'video/mp4' ,
19- 'X-Filename' : encodeURIComponent ( file . name ) ,
20- } ,
21- body : file ,
2253 } )
2354
24- if ( ! response . ok ) {
25- const text = await response . text ( )
26- let message = `Upload failed (${ response . status } )`
27- try {
28- const json = JSON . parse ( text )
29- if ( json . error ) message = json . error
30- } catch { /* ignore */ }
31- throw new Error ( message )
55+ if ( ! finalRes . ok ) {
56+ throw new Error ( 'Failed to finalize upload' )
3257 }
3358
34- onProgress ( 100 )
35- return response . json ( )
59+ return finalRes . json ( )
3660}
3761
3862export async function deleteVideo ( id : string ) : Promise < void > {
0 commit comments