1
1
import md5 from 'md5'
2
2
import JSZip from 'jszip'
3
3
import FileSaver from 'jszip/vendor/FileSaver'
4
- const noop = ( func , defaultFunc ) => {
4
+
5
+ // 每段数量上限
6
+ export const partLimit = 1e3
7
+ // 同时请求数上限
8
+ export const requestLimit = 5
9
+
10
+ export const noop = ( func , defaultFunc ) => {
5
11
return typeof func === 'function' ? func : typeof defaultFunc === 'function' ? defaultFunc : ( ) => { }
6
12
}
7
13
8
- const ajax = ( options ) => {
14
+ export const ajax = ( options ) => {
9
15
var xhr = new XMLHttpRequest ( )
10
16
options . method = options . method || 'get'
11
17
xhr . responseType = options . dataType || 'json' ;
@@ -32,39 +38,79 @@ const ajax = (options) => {
32
38
}
33
39
}
34
40
35
- export const downloadZip = ( fileName , files ) => {
36
- fileName = fileName || md5 ( files . map ( item => item . downloadUrl ) . join ( '|' ) )
37
- const zip = new JSZip ( )
38
- const fetchFile = ( file ) => {
39
- return new Promise ( ( resolve , reject ) => {
40
- if ( file . content ) {
41
- const blob = new Blob ( [ file . content ] , { type : file . type || 'text/plain' } )
42
- zip . file ( file . name , blob )
43
- resolve ( blob )
44
- } else {
45
- ajax ( {
46
- url : file . downloadUrl ,
47
- type : 'get' ,
48
- data : '' ,
49
- dataType : 'blob' ,
50
- success : ( blob ) => {
51
- zip . file ( file . name , blob ) ;
52
- resolve ( blob )
53
- } ,
54
- error : reject
41
+ export const fetchBlobFile = ( file ) => {
42
+ return new Promise ( ( resolve , reject ) => {
43
+ if ( file . content ) {
44
+ resolve ( new Blob ( [ file . content ] , { type : file . type || 'text/plain' } ) )
45
+ } else {
46
+ ajax ( {
47
+ url : file . downloadUrl ,
48
+ type : 'get' ,
49
+ data : '' ,
50
+ dataType : 'blob' ,
51
+ success : ( blob ) => {
52
+ resolve ( blob )
53
+ } ,
54
+ error : ( ) => {
55
+ resolve ( new Blob ( [ file . downloadUrl ] , { type : 'text/plain' } ) )
56
+ }
57
+ } )
58
+ }
59
+ } )
60
+ }
61
+
62
+ export const partTask = ( items , handler , num = requestLimit ) => {
63
+ let index = 0
64
+ let list = items . slice ( 0 )
65
+ let queue = Promise . resolve ( )
66
+ const result = [ ]
67
+ while ( list . length ) {
68
+ const current = list . splice ( 0 , num )
69
+ const currentIndex = index ++
70
+ queue = queue . then ( ( ) => {
71
+ return new Promise ( ( resolve ) => {
72
+ Promise . all ( handler ( current , currentIndex ) ) . then ( datas => {
73
+ result . push . apply ( result , datas )
55
74
} )
56
- }
75
+ . finally ( ( ) => resolve ( result ) )
76
+ } )
57
77
} )
58
78
}
59
- return Promise . all (
60
- files . map ( file => fetchFile ( file ) )
61
- ) . then ( ( datas ) => {
62
- zip . generateAsync ( {
79
+ return queue
80
+ }
81
+
82
+ export const partRequest = ( fileName , files ) => {
83
+ const zip = new JSZip ( )
84
+ const handler = ( files ) => files . map ( file => fetchBlobFile ( file , zip ) . then ( blob => {
85
+ zip . file ( file . name , blob )
86
+ return blob
87
+ } ) )
88
+ return partTask ( files , handler , requestLimit ) . then ( ( datas ) => {
89
+ return zip . generateAsync ( {
63
90
type : "blob"
64
- } ) . then ( function ( content ) {
65
- FileSaver ( content , fileName + '.zip' ) ;
91
+ } ) . then ( ( content ) => {
92
+ return new Promise ( ( resolve ) => {
93
+ FileSaver ( content , fileName ) ;
94
+ setTimeout ( ( ) => {
95
+ resolve ( )
96
+ } , 1.5e4 )
97
+ } )
66
98
} )
67
99
} )
68
100
}
69
101
102
+ export const partDownload = ( fileName , files ) => {
103
+ const count = ~ ~ ( files . length / partLimit )
104
+ return partTask ( files , ( files , index ) => {
105
+ const partMame = count >= 1 ? '-p' + ( index + 1 ) + '-' + count : ''
106
+ const name = fileName + partMame + '.zip'
107
+ return [ partRequest ( name , files ) ]
108
+ } , partLimit )
109
+ }
110
+
111
+ export const downloadZip = ( fileName , files ) => {
112
+ fileName = fileName || md5 ( files . map ( item => item . downloadUrl ) . join ( '|' ) )
113
+ return partDownload ( fileName , files )
114
+ }
115
+
70
116
export default downloadZip
0 commit comments