|
@@ -27,6 +27,7 @@ export default class Blob extends EventTarget {
|
27
|
27
|
_ref:string = null;
|
28
|
28
|
_blobCreated:boolean = false;
|
29
|
29
|
_onCreated:Array<any> = [];
|
|
30
|
+ _closed:boolean = false;
|
30
|
31
|
|
31
|
32
|
/**
|
32
|
33
|
* Static method that remove all files in Blob cache folder.
|
|
@@ -37,6 +38,12 @@ export default class Blob extends EventTarget {
|
37
|
38
|
return fs.unlink(blobCacheDir).then(() => fs.mkdir(blobCacheDir))
|
38
|
39
|
}
|
39
|
40
|
|
|
41
|
+ static build(data:any, cType:any):Promise<Blob> {
|
|
42
|
+ return new Promise((resolve, reject) => {
|
|
43
|
+ new Blob(data, cType).onCreated(resolve)
|
|
44
|
+ })
|
|
45
|
+ }
|
|
46
|
+
|
40
|
47
|
/**
|
41
|
48
|
* RNFetchBlob Blob polyfill, create a Blob directly from file path, BASE64
|
42
|
49
|
* encoded data, and string. The conversion is done implicitly according to
|
|
@@ -52,10 +59,12 @@ export default class Blob extends EventTarget {
|
52
|
59
|
this.cacheName = getBlobName()
|
53
|
60
|
this.isRNFetchBlobPolyfill = true
|
54
|
61
|
this.type = cType.type || 'text/plain'
|
55
|
|
- log.verbose('Blob constructor called', 'mime', this.type, 'type', typeof data, 'length', data.length)
|
|
62
|
+ log.verbose('Blob constructor called', 'mime', this.type, 'type', typeof data, 'length', data? data.length:0)
|
56
|
63
|
this._ref = blobCacheDir + this.cacheName
|
57
|
64
|
let p = null
|
58
|
|
- if(data instanceof Blob) {
|
|
65
|
+ if(!data)
|
|
66
|
+ data = ''
|
|
67
|
+ if(data.isRNFetchBlobPolyfill) {
|
59
|
68
|
log.verbose('create Blob cache file from Blob object')
|
60
|
69
|
let size = 0
|
61
|
70
|
this._ref = String(data.getRNFetchBlobRef())
|
|
@@ -72,6 +81,28 @@ export default class Blob extends EventTarget {
|
72
|
81
|
throw `could not create Blob from path ${orgPath}, file not exists`
|
73
|
82
|
})
|
74
|
83
|
}
|
|
84
|
+ // process FormData
|
|
85
|
+ else if(data instanceof FormData) {
|
|
86
|
+ log.verbose('create Blob cache file from FormData', data)
|
|
87
|
+ let boundary = `--RNFetchBlob-${this.cacheName}-${Date.now()}\r\n`
|
|
88
|
+ let parts = data.getParts()
|
|
89
|
+ let formArray = []
|
|
90
|
+ for(let i in parts) {
|
|
91
|
+ formArray.push(boundary)
|
|
92
|
+ let part = parts[i]
|
|
93
|
+ for(let j in part.headers) {
|
|
94
|
+ formArray.push(j + part.headers[j] + ';\r\n')
|
|
95
|
+ }
|
|
96
|
+ formArray.push('\r\n')
|
|
97
|
+ if(part.isRNFetchBlobPolyfill)
|
|
98
|
+ formArray.push(part)
|
|
99
|
+ else
|
|
100
|
+ formArray.push(part.string)
|
|
101
|
+ }
|
|
102
|
+ log.verbose('FormData array', formArray)
|
|
103
|
+ formArray.push(boundary + '--')
|
|
104
|
+ p = createMixedBlobData(this._ref, formArray)
|
|
105
|
+ }
|
75
|
106
|
// if the data is a string starts with `RNFetchBlob-file://`, append the
|
76
|
107
|
// Blob data from file path
|
77
|
108
|
else if(typeof data === 'string' && data.startsWith('RNFetchBlob-file://')) {
|
|
@@ -127,15 +158,16 @@ export default class Blob extends EventTarget {
|
127
|
158
|
* Since Blob content will asynchronously write to a file during creation,
|
128
|
159
|
* use this method to register an event handler for Blob initialized event.
|
129
|
160
|
* @nonstandard
|
130
|
|
- * @param {[type]} fn:( [description]
|
131
|
|
- * @return {[type]} [description]
|
|
161
|
+ * @param {(b:Blob) => void} An event handler invoked when Blob created
|
|
162
|
+ * @return {Blob} The Blob object instance itself
|
132
|
163
|
*/
|
133
|
|
- onCreated(fn:() => void) {
|
|
164
|
+ onCreated(fn:() => void):Blob {
|
134
|
165
|
log.verbose('register blob onCreated', this._onCreated.length)
|
135
|
166
|
if(!this._blobCreated)
|
136
|
167
|
this._onCreated.push(fn)
|
137
|
168
|
else
|
138
|
169
|
fn(this)
|
|
170
|
+ return this
|
139
|
171
|
}
|
140
|
172
|
|
141
|
173
|
/**
|
|
@@ -155,7 +187,9 @@ export default class Blob extends EventTarget {
|
155
|
187
|
* @return {Blob}
|
156
|
188
|
*/
|
157
|
189
|
slice(start:?number, end:?number, encoding:?string):Blob {
|
158
|
|
- log.verbose('slice called')
|
|
190
|
+ if(this._closed)
|
|
191
|
+ throw 'Blob has been released.'
|
|
192
|
+ log.verbose('slice called', start, end, encoding)
|
159
|
193
|
// TODO : fs.slice
|
160
|
194
|
// return fs.slice(this.cacheName, getBlobName(), contentType, start, end)
|
161
|
195
|
}
|
|
@@ -166,6 +200,9 @@ export default class Blob extends EventTarget {
|
166
|
200
|
* @return {Promise}
|
167
|
201
|
*/
|
168
|
202
|
close() {
|
|
203
|
+ if(this._closed)
|
|
204
|
+ return Promise.reject('Blob has been released.')
|
|
205
|
+ this._closed = true
|
169
|
206
|
return fs.unlink(this._ref)
|
170
|
207
|
}
|
171
|
208
|
|