Browse Source

Add closed private property to Blob #44

Ben Hsieh 8 years ago
parent
commit
4ef854007b
2 changed files with 44 additions and 8 deletions
  1. 43
    6
      src/polyfill/Blob.js
  2. 1
    2
      src/polyfill/index.js

+ 43
- 6
src/polyfill/Blob.js View File

27
   _ref:string = null;
27
   _ref:string = null;
28
   _blobCreated:boolean = false;
28
   _blobCreated:boolean = false;
29
   _onCreated:Array<any> = [];
29
   _onCreated:Array<any> = [];
30
+  _closed:boolean = false;
30
 
31
 
31
   /**
32
   /**
32
    * Static method that remove all files in Blob cache folder.
33
    * Static method that remove all files in Blob cache folder.
37
     return fs.unlink(blobCacheDir).then(() => fs.mkdir(blobCacheDir))
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
    * RNFetchBlob Blob polyfill, create a Blob directly from file path, BASE64
48
    * RNFetchBlob Blob polyfill, create a Blob directly from file path, BASE64
42
    * encoded data, and string. The conversion is done implicitly according to
49
    * encoded data, and string. The conversion is done implicitly according to
52
     this.cacheName = getBlobName()
59
     this.cacheName = getBlobName()
53
     this.isRNFetchBlobPolyfill = true
60
     this.isRNFetchBlobPolyfill = true
54
     this.type = cType.type || 'text/plain'
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
     this._ref = blobCacheDir + this.cacheName
63
     this._ref = blobCacheDir + this.cacheName
57
     let p = null
64
     let p = null
58
-    if(data instanceof Blob) {
65
+    if(!data)
66
+      data = ''
67
+    if(data.isRNFetchBlobPolyfill) {
59
       log.verbose('create Blob cache file from Blob object')
68
       log.verbose('create Blob cache file from Blob object')
60
       let size = 0
69
       let size = 0
61
       this._ref = String(data.getRNFetchBlobRef())
70
       this._ref = String(data.getRNFetchBlobRef())
72
                 throw `could not create Blob from path ${orgPath}, file not exists`
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
     // if the data is a string starts with `RNFetchBlob-file://`, append the
106
     // if the data is a string starts with `RNFetchBlob-file://`, append the
76
     // Blob data from file path
107
     // Blob data from file path
77
     else if(typeof data === 'string' && data.startsWith('RNFetchBlob-file://')) {
108
     else if(typeof data === 'string' && data.startsWith('RNFetchBlob-file://')) {
127
    * Since Blob content will asynchronously write to a file during creation,
158
    * Since Blob content will asynchronously write to a file during creation,
128
    * use this method to register an event handler for Blob initialized event.
159
    * use this method to register an event handler for Blob initialized event.
129
    * @nonstandard
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
     log.verbose('register blob onCreated', this._onCreated.length)
165
     log.verbose('register blob onCreated', this._onCreated.length)
135
     if(!this._blobCreated)
166
     if(!this._blobCreated)
136
       this._onCreated.push(fn)
167
       this._onCreated.push(fn)
137
     else
168
     else
138
       fn(this)
169
       fn(this)
170
+    return this
139
   }
171
   }
140
 
172
 
141
   /**
173
   /**
155
    * @return {Blob}
187
    * @return {Blob}
156
    */
188
    */
157
   slice(start:?number, end:?number, encoding:?string):Blob {
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
     // TODO : fs.slice
193
     // TODO : fs.slice
160
     // return fs.slice(this.cacheName, getBlobName(), contentType, start, end)
194
     // return fs.slice(this.cacheName, getBlobName(), contentType, start, end)
161
   }
195
   }
166
    * @return {Promise}
200
    * @return {Promise}
167
    */
201
    */
168
   close() {
202
   close() {
203
+    if(this._closed)
204
+      return Promise.reject('Blob has been released.')
205
+    this._closed = true
169
     return fs.unlink(this._ref)
206
     return fs.unlink(this._ref)
170
   }
207
   }
171
 
208
 

+ 1
- 2
src/polyfill/index.js View File

1
 import Blob from './Blob.js'
1
 import Blob from './Blob.js'
2
 import File from './File.js'
2
 import File from './File.js'
3
 import XMLHttpRequest from './XMLHttpRequest.js'
3
 import XMLHttpRequest from './XMLHttpRequest.js'
4
-import FormData from './FormData.js'
5
 import ProgressEvent from './ProgressEvent'
4
 import ProgressEvent from './ProgressEvent'
6
 import Event from './Event'
5
 import Event from './Event'
7
 
6
 
8
 export default {
7
 export default {
9
-  Blob, File, XMLHttpRequest, FormData, ProgressEvent, Event
8
+  Blob, File, XMLHttpRequest, ProgressEvent, Event
10
 }
9
 }