@@ -237,6 +237,16 @@ function extend(target, source) {
237237function isArray ( arr ) {
238238 return arr instanceof Array ;
239239}
240+ function isInArray ( arr , item ) {
241+ var flag = false ;
242+ for ( var i = 0 ; i < arr . length ; i ++ ) {
243+ if ( item === arr [ i ] ) {
244+ flag = true ;
245+ break ;
246+ }
247+ }
248+ return flag ;
249+ }
240250function each ( obj , fn ) {
241251 for ( var i in obj ) {
242252 if ( obj . hasOwnProperty ( i ) ) {
@@ -464,6 +474,7 @@ var util = {
464474 binaryBase64 : binaryBase64 ,
465475 extend : extend ,
466476 isArray : isArray ,
477+ isInArray : isInArray ,
467478 each : each ,
468479 map : map ,
469480 filter : filter ,
@@ -1461,7 +1472,7 @@ var initTask = function (cos) {
14611472 return ;
14621473 }
14631474 task . state = switchToState ;
1464- cos . emit ( 'inner-kill-task' , { TaskId : id } ) ;
1475+ cos . emit ( 'inner-kill-task' , { TaskId : id , toState : switchToState } ) ;
14651476 emitListUpdate ( ) ;
14661477 if ( running ) {
14671478 uploadingFileCount -- ;
@@ -8035,28 +8046,36 @@ function sliceUploadFile(params, callback) {
80358046 } ) ;
80368047
80378048 // 上传分块完成,开始 uploadSliceComplete 操作
8038- ep . on ( 'upload_slice_complete' , function ( data ) {
8049+ ep . on ( 'upload_slice_complete' , function ( UploadData ) {
80398050 uploadSliceComplete . call ( self , {
80408051 Bucket : Bucket ,
80418052 Region : Region ,
80428053 Key : Key ,
8043- UploadId : data . UploadId ,
8044- SliceList : data . SliceList
8054+ UploadId : UploadData . UploadId ,
8055+ SliceList : UploadData . SliceList
80458056 } , function ( err , data ) {
80468057 if ( ! self . _isRunningTask ( TaskId ) ) return ;
8058+ delete uploadIdUsing [ UploadData . UploadId ] ;
80478059 if ( err ) {
80488060 return ep . emit ( 'error' , err ) ;
80498061 }
8062+ removeUploadId . call ( self , UploadData . UploadId ) ;
80508063 ep . emit ( 'upload_complete' , data ) ;
80518064 } ) ;
80528065 } ) ;
80538066
80548067 // 获取 UploadId 完成,开始上传每个分片
80558068 ep . on ( 'get_upload_data_finish' , function ( UploadData ) {
8056- if ( UploadData . UploadId ) {
8057- var uuid = getFileUuid ( Body , params . ChunkSize ) ;
8058- uuid && setUploadId . call ( self , uuid , UploadData . UploadId ) ;
8059- }
8069+
8070+ // 处理 UploadId 缓存
8071+ var uuid = getFileUuid ( Body , params . ChunkSize ) ;
8072+ uuid && setUploadId . call ( self , uuid , UploadData . UploadId ) ; // 缓存 UploadId
8073+ uploadIdUsing [ UploadData . UploadId ] = true ; // 标记 UploadId 为正在使用
8074+ TaskId && self . on ( 'inner-kill-task' , function ( data ) {
8075+ if ( data . TaskId === TaskId && data . toState === 'canceled' ) {
8076+ delete uploadIdUsing [ UploadData . UploadId ] ; // 去除 UploadId 正在使用的标记
8077+ }
8078+ } ) ;
80608079
80618080 // 获取 UploadId
80628081 uploadSliceList . call ( self , {
@@ -8126,6 +8145,7 @@ function sliceUploadFile(params, callback) {
81268145 params . ChunkSize = params . SliceSize = ChunkSize = Math . max ( ChunkSize , AutoChunkSize ) ;
81278146 } ) ( ) ;
81288147
8148+ // 开始上传
81298149 if ( FileSize === 0 ) {
81308150 params . Body = '' ;
81318151 self . putObject ( params , callback ) ;
@@ -8135,14 +8155,26 @@ function sliceUploadFile(params, callback) {
81358155}
81368156
81378157// 按照文件特征值,缓存 UploadId
8158+ var uploadIdCache ;
8159+ var uploadIdUsing = { } ;
81388160var uploadIdCacheKey = 'cos_sdk_upload_cache' ;
8139- var uploadIdCache = [ ] ;
8140- try {
8141- uploadIdCache = JSON . parse ( localStorage . getItem ( uploadIdCacheKey ) ) || [ ] ;
8142- } catch ( e ) { }
8143- function setUploadId ( uuid , UploadId ) {
8161+ function initUploadId ( ) {
8162+ var cacheLimit = this . options . UploadIdCacheLimit ;
8163+ if ( ! uploadIdCache ) {
8164+ if ( cacheLimit ) {
8165+ try {
8166+ uploadIdCache = JSON . parse ( localStorage . getItem ( uploadIdCacheKey ) ) || [ ] ;
8167+ } catch ( e ) { }
8168+ }
8169+ if ( ! uploadIdCache ) {
8170+ uploadIdCache = [ ] ;
8171+ }
8172+ }
8173+ }
8174+ function setUploadId ( uuid , UploadId , isDisabled ) {
8175+ initUploadId . call ( this ) ;
81448176 for ( var i = uploadIdCache . length - 1 ; i >= 0 ; i -- ) {
8145- if ( uploadIdCache [ i ] [ 0 ] === uuid ) {
8177+ if ( uploadIdCache [ i ] [ 0 ] === uuid && uploadIdCache [ i ] [ 1 ] === UploadId ) {
81468178 uploadIdCache . splice ( i , 1 ) ;
81478179 }
81488180 }
@@ -8157,15 +8189,37 @@ function setUploadId(uuid, UploadId) {
81578189 } catch ( e ) { }
81588190 } ) ;
81598191}
8192+ function removeUploadId ( UploadId ) {
8193+ initUploadId . call ( this ) ;
8194+ delete uploadIdUsing [ UploadId ] ;
8195+ for ( var i = uploadIdCache . length - 1 ; i >= 0 ; i -- ) {
8196+ if ( uploadIdCache [ i ] [ 1 ] === UploadId ) {
8197+ uploadIdCache . splice ( i , 1 ) ;
8198+ }
8199+ }
8200+ var cacheLimit = this . options . UploadIdCacheLimit ;
8201+ if ( uploadIdCache . length > cacheLimit ) {
8202+ uploadIdCache . splice ( cacheLimit ) ;
8203+ }
8204+ cacheLimit && setTimeout ( function ( ) {
8205+ try {
8206+ if ( uploadIdCache . length ) {
8207+ localStorage . setItem ( uploadIdCacheKey , JSON . stringify ( uploadIdCache ) ) ;
8208+ } else {
8209+ localStorage . removeItem ( uploadIdCacheKey ) ;
8210+ }
8211+ } catch ( e ) { }
8212+ } ) ;
8213+ }
81608214function getUploadId ( uuid ) {
8161- var UploadId ;
8215+ initUploadId . call ( this ) ;
8216+ var CacheUploadIdList = [ ] ;
81628217 for ( var i = 0 ; i < uploadIdCache . length ; i ++ ) {
81638218 if ( uploadIdCache [ i ] [ 0 ] === uuid ) {
8164- UploadId = uploadIdCache [ i ] [ 1 ] ;
8165- break ;
8219+ CacheUploadIdList . push ( uploadIdCache [ i ] [ 1 ] ) ;
81668220 }
81678221 }
8168- return UploadId ;
8222+ return CacheUploadIdList . length ? CacheUploadIdList : null ;
81698223}
81708224function getFileUuid ( file , ChunkSize ) {
81718225 // 如果信息不完整,不获取
@@ -8318,14 +8372,23 @@ function getUploadIdAndPartList(params, callback) {
83188372 UploadIdList = UploadIdList . reverse ( ) ;
83198373 Async . eachLimit ( UploadIdList , 1 , function ( UploadId , asyncCallback ) {
83208374 if ( ! self . _isRunningTask ( TaskId ) ) return ;
8375+ // 如果正在上传,跳过
8376+ if ( uploadIdUsing [ UploadId ] ) {
8377+ asyncCallback ( ) ; // 检查下一个 UploadId
8378+ return ;
8379+ }
8380+ // 判断 UploadId 是否可用
83218381 wholeMultipartListPart . call ( self , {
83228382 Bucket : Bucket ,
83238383 Region : Region ,
83248384 Key : Key ,
83258385 UploadId : UploadId
83268386 } , function ( err , PartListData ) {
83278387 if ( ! self . _isRunningTask ( TaskId ) ) return ;
8328- if ( err ) return ep . emit ( 'error' , err ) ;
8388+ if ( err ) {
8389+ removeUploadId . call ( self , UploadId ) ;
8390+ return ep . emit ( 'error' , err ) ;
8391+ }
83298392 var PartList = PartListData . PartList ;
83308393 PartList . forEach ( function ( item ) {
83318394 item . PartNumber *= 1 ;
@@ -8356,24 +8419,58 @@ function getUploadIdAndPartList(params, callback) {
83568419 } ) ;
83578420 } ) ;
83588421
8359- // 获取缓存的 UploadId
8360- var uuid = getFileUuid ( params . Body , params . ChunkSize ) ,
8361- UploadId ;
8362- if ( uuid && ( UploadId = getUploadId ( uuid ) ) ) {
8363- wholeMultipartListPart . call ( self , {
8364- Bucket : Bucket ,
8365- Region : Region ,
8366- Key : Key ,
8367- UploadId : UploadId
8368- } , function ( err , PartListData ) {
8369- if ( ! self . _isRunningTask ( TaskId ) ) return ;
8370- if ( err ) return ep . emit ( 'error' , err ) ;
8371- ep . emit ( 'upload_id_ready' , {
8372- UploadId : UploadId ,
8373- PartList : PartListData . PartList
8374- } ) ;
8375- } ) ;
8376- } else {
8422+ // 在本地缓存找可用的 UploadId
8423+ ep . on ( 'seek_local_avail_upload_id' , function ( RemoteUploadIdList ) {
8424+ // 在本地找可用的 UploadId
8425+ var uuid = getFileUuid ( params . Body , params . ChunkSize ) ,
8426+ LocalUploadIdList ;
8427+ if ( uuid && ( LocalUploadIdList = getUploadId . call ( self , uuid ) ) ) {
8428+ var next = function ( index ) {
8429+ // 如果找不到,到线上列出 UploadId
8430+ if ( index >= LocalUploadIdList . length ) {
8431+ ep . emit ( 'has_upload_id' , RemoteUploadIdList ) ;
8432+ return ;
8433+ }
8434+ var UploadId = LocalUploadIdList [ index ] ;
8435+ // 如果不在远端 UploadId 列表里,跳过并删除
8436+ if ( ! util . isInArray ( RemoteUploadIdList , UploadId ) ) {
8437+ removeUploadId . call ( self , UploadId ) ;
8438+ next ( index + 1 ) ;
8439+ return ;
8440+ }
8441+ // 如果正在上传,跳过
8442+ if ( uploadIdUsing [ UploadId ] ) {
8443+ next ( index + 1 ) ;
8444+ return ;
8445+ }
8446+ // 判断 UploadId 是否存在线上
8447+ wholeMultipartListPart . call ( self , {
8448+ Bucket : Bucket ,
8449+ Region : Region ,
8450+ Key : Key ,
8451+ UploadId : UploadId
8452+ } , function ( err , PartListData ) {
8453+ if ( ! self . _isRunningTask ( TaskId ) ) return ;
8454+ if ( err ) {
8455+ removeUploadId . call ( self , UploadId ) ;
8456+ next ( index + 1 ) ;
8457+ } else {
8458+ // 找到可用 UploadId
8459+ ep . emit ( 'upload_id_ready' , {
8460+ UploadId : UploadId ,
8461+ PartList : PartListData . PartList
8462+ } ) ;
8463+ }
8464+ } ) ;
8465+ } ;
8466+ next ( 0 ) ;
8467+ } else {
8468+ ep . emit ( 'has_upload_id' , RemoteUploadIdList ) ;
8469+ }
8470+ } ) ;
8471+
8472+ // 获取线上 UploadId 列表
8473+ ep . on ( 'get_remote_upload_id_list' , function ( RemoteUploadIdList ) {
83778474 // 获取符合条件的 UploadId 列表,因为同一个文件可以有多个上传任务。
83788475 wholeMultipartList . call ( self , {
83798476 Bucket : Bucket ,
@@ -8384,18 +8481,29 @@ function getUploadIdAndPartList(params, callback) {
83848481 if ( err ) {
83858482 return ep . emit ( 'error' , err ) ;
83868483 }
8387- var UploadIdList = data . UploadList . filter ( function ( item ) {
8484+ // 整理远端 UploadId 列表
8485+ var RemoteUploadIdList = data . UploadList . filter ( function ( item ) {
83888486 return item . Key === Key && ( ! StorageClass || item . StorageClass . toUpperCase ( ) === StorageClass . toUpperCase ( ) ) ;
83898487 } ) . reverse ( ) . map ( function ( item ) {
83908488 return item . UploadId || item . UploadID ;
83918489 } ) ;
8392- if ( UploadIdList . length ) {
8393- ep . emit ( 'has_upload_id ' , UploadIdList ) ;
8490+ if ( RemoteUploadIdList . length ) {
8491+ ep . emit ( 'seek_local_avail_upload_id ' , RemoteUploadIdList ) ;
83948492 } else {
8493+ var uuid = getFileUuid ( params . Body , params . ChunkSize ) ,
8494+ LocalUploadIdList ;
8495+ if ( uuid && ( LocalUploadIdList = getUploadId . call ( self , uuid ) ) ) {
8496+ util . each ( LocalUploadIdList , function ( UploadId ) {
8497+ removeUploadId . call ( self , UploadId ) ;
8498+ } ) ;
8499+ }
83958500 ep . emit ( 'no_available_upload_id' ) ;
83968501 }
83978502 } ) ;
8398- }
8503+ } ) ;
8504+
8505+ // 开始找可用 UploadId
8506+ ep . emit ( 'get_remote_upload_id_list' ) ;
83998507}
84008508
84018509// 获取符合条件的全部上传任务 (条件包括 Bucket, Region, Prefix)
0 commit comments