@@ -4,6 +4,7 @@ import { FileEncryption } from './encryption';
44export class ChunkedUpload {
55 private static readonly CHUNK_SIZE = 5 * 1024 * 1024 ; // 5MB chunks
66 private static readonly MAX_RETRIES = 3 ;
7+ private static readonly CONCURRENCY = 3 ;
78
89 static async uploadFileInChunks (
910 file : File ,
@@ -15,7 +16,7 @@ export class ChunkedUpload {
1516 await FileEncryption . encryptFile ( file , this . CHUNK_SIZE ) ;
1617
1718 const totalSize = file . size + totalChunks * 16 ; // approximate with GCM tag
18-
19+
1920 console . log (
2021 `Starting chunked upload: ${ totalChunks } chunks, ${ this . formatSize ( totalSize ) } total`
2122 ) ;
@@ -44,18 +45,38 @@ export class ChunkedUpload {
4445 const { uploadId } = await sessionResponse . json ( ) ;
4546 console . log ( 'Upload session started:' , uploadId ) ;
4647
48+
49+ const activeUploads = new Set < Promise < void > > ( ) ;
4750 let chunkIndex = 0 ;
51+ let uploaded = 0 ;
52+
4853 for await ( const chunk of encryptedStream ) {
49- await this . uploadChunkWithRetry (
54+ const currentIndex = chunkIndex ++ ;
55+ const task = this . uploadChunkWithRetry (
5056 uploadId ,
51- chunkIndex ,
57+ currentIndex ,
5258 chunk ,
53- totalChunks ,
54- onProgress
59+ totalChunks
5560 ) ;
56- chunkIndex ++ ;
61+ activeUploads . add ( task ) ;
62+
63+ task
64+ . then ( ( ) => {
65+ uploaded ++ ;
66+ if ( onProgress ) {
67+ const progress = Math . round ( ( uploaded / totalChunks ) * 100 ) ;
68+ onProgress ( progress ) ;
69+ }
70+ } )
71+ . finally ( ( ) => activeUploads . delete ( task ) ) ;
72+
73+ if ( activeUploads . size >= this . CONCURRENCY ) {
74+ await Promise . race ( activeUploads ) ;
75+ }
5776 }
5877
78+ await Promise . all ( activeUploads ) ;
79+
5980 // Complete upload
6081 const completeResponse = await fetch ( '/api/upload/complete' , {
6182 method : 'POST' ,
@@ -68,6 +89,7 @@ export class ChunkedUpload {
6889 throw new Error ( 'Failed to complete upload' ) ;
6990 }
7091
92+
7193 return await completeResponse . json ( ) ;
7294 } catch ( error ) {
7395 console . error ( 'Chunked upload failed:' , error ) ;
@@ -103,8 +125,9 @@ export class ChunkedUpload {
103125 const progress = Math . round ( ( ( chunkIndex + 1 ) / totalChunks ) * 100 ) ;
104126 onProgress ( progress ) ;
105127 }
106-
107- console . log ( `Chunk ${ chunkIndex + 1 } /${ totalChunks } uploaded successfully` ) ;
128+ console . log (
129+ `Chunk ${ chunkIndex + 1 } /${ totalChunks } uploaded successfully`
130+ ) ;
108131 } catch ( error ) {
109132 console . error ( `Error uploading chunk ${ chunkIndex } :` , error ) ;
110133 if ( retryCount < this . MAX_RETRIES ) {
0 commit comments