소스 검색

#44 successfully upload file to Firebase storage

Ben Hsieh 8 년 전
부모
커밋
9607725047
6개의 변경된 파일110개의 추가작업 그리고 152개의 파일을 삭제
  1. 1
    0
      src/fs.js
  2. 23
    40
      src/ios/RNFetchBlobFS.m
  3. 0
    2
      src/ios/RNFetchBlobNetwork.m
  4. 23
    27
      src/ios/RNFetchBlobReqBuilder.m
  5. 59
    80
      src/polyfill/Blob.js
  6. 4
    3
      src/polyfill/XMLHttpRequest.js

+ 1
- 0
src/fs.js 파일 보기

@@ -173,6 +173,7 @@ function writeFile(path:string, data:string | Array<number>, encoding:?string):P
173 173
 
174 174
 function appendFile(path:string, data:string | Array<number>, encoding:?string):Promise {
175 175
   encoding = encoding || 'utf8'
176
+  console.log('fs append file', data, encoding)
176 177
   if(typeof path !== 'string')
177 178
     return Promise.reject('Invalid argument "path" ')
178 179
   if(encoding.toLocaleLowerCase() === 'ascii') {

+ 23
- 40
src/ios/RNFetchBlobFS.m 파일 보기

@@ -213,49 +213,32 @@ NSMutableDictionary *fileStreams = nil;
213 213
         encoding = [encoding lowercaseString];
214 214
         if(![fm fileExistsAtPath:folder]) {
215 215
             [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
216
+            [fm createFileAtPath:path contents:nil attributes:nil];
216 217
         }
217
-        // if file exists, write file using encoding
218
-        if(![fm fileExistsAtPath:path]) {
219
-            if([encoding isEqualToString:@"base64"]){
220
-                NSData * byteData = [[NSData alloc] initWithBase64EncodedString:data options:0];
221
-                [fm createFileAtPath:path contents:byteData attributes:NULL];
222
-            }
223
-            // write file from file
224
-            else if([encoding isEqualToString:@"uri"]) {
225
-                [[self class] writeFileFromFile:data toFile:path append:append];
226
-                resolve([NSNull null]);
227
-                return;
228
-            }
229
-            //TODO: from buffer
230
-            // else if ([encoding isEqualToString:@"buffer"]){
231
-            // }
232
-            // write data as UTF8 string
233
-            else
234
-                [fm createFileAtPath:path contents:[data dataUsingEncoding:NSUTF8StringEncoding] attributes:NULL];
218
+        if(err != nil) {
219
+            reject(@"RNFetchBlob writeFile Error", @"could not create file at path", path);
220
+            return;
221
+        }
222
+        NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
223
+        NSData * content = nil;
224
+        if([encoding isEqualToString:@"base64"]) {
225
+            content = [[NSData alloc] initWithBase64EncodedString:data options:0];
226
+        }
227
+        else if([encoding isEqualToString:@"uri"]) {
228
+            [[self class] writeFileFromFile:data toFile:path append:append];
229
+            resolve([NSNull null]);
230
+            return;
235 231
         }
236
-        // file does not exists, create one
237 232
         else {
238
-            NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
239
-            NSData * content = nil;
240
-            if([encoding isEqualToString:@"base64"]) {
241
-                content = [[NSData alloc] initWithBase64EncodedString:data options:0];
242
-            }
243
-            else if([encoding isEqualToString:@"uri"]) {
244
-                [[self class] writeFileFromFile:data toFile:path append:append];
245
-                resolve([NSNull null]);
246
-                return;
247
-            }
248
-            else {
249
-                content = [data dataUsingEncoding:NSUTF8StringEncoding];
250
-            }
251
-            if(append == YES) {
252
-                [fileHandle seekToEndOfFile];
253
-                [fileHandle writeData:content];
254
-                [fileHandle closeFile];
255
-            }
256
-            else {
257
-                [content writeToFile:path atomically:YES];
258
-            }
233
+            content = [data dataUsingEncoding:NSUTF8StringEncoding];
234
+        }
235
+        if(append == YES) {
236
+            [fileHandle seekToEndOfFile];
237
+            [fileHandle writeData:content];
238
+            [fileHandle closeFile];
239
+        }
240
+        else {
241
+            [content writeToFile:path atomically:YES];
259 242
         }
260 243
         fm = nil;
261 244
         resolve([NSNull null]);

+ 0
- 2
src/ios/RNFetchBlobNetwork.m 파일 보기

@@ -134,8 +134,6 @@ NSOperationQueue *taskQueue;
134 134
 
135 135
         if(path != nil)
136 136
             destPath = path;
137
-        // else
138
-        //     destPath = [RNFetchBlobFS getTempPath:cacheKey withExtension:[self.options valueForKey:CONFIG_FILE_EXT]];
139 137
     }
140 138
     else
141 139
     {

+ 23
- 27
src/ios/RNFetchBlobReqBuilder.m 파일 보기

@@ -86,7 +86,13 @@
86 86
         if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
87 87
             // generate octet-stream body
88 88
             if(body != nil) {
89
-
89
+                
90
+                // when headers does not contain a key named "content-type" (case ignored), use default content type
91
+                if([[self class] getHeaderIgnoreCases:@"content-type" fromHeaders:mheaders] == nil)
92
+                {
93
+                    [mheaders setValue:@"application/octet-stream" forKey:@"Content-Type"];
94
+                }
95
+                
90 96
                 // when body is a string contains file path prefix, try load file from the path
91 97
                 if([body hasPrefix:FILE_PREFIX]) {
92 98
                     NSString * orgPath = [body substringFromIndex:[FILE_PREFIX length]];
@@ -95,10 +101,6 @@
95 101
                     {
96 102
                         [RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
97 103
                             [request setHTTPBody:content];
98
-                            if([mheaders valueForKey:@"content-type"] == nil)
99
-                            {
100
-                                [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
101
-                            }
102 104
                             [request setHTTPMethod: method];
103 105
                             [request setAllHTTPHeaderFields:mheaders];
104 106
                             onComplete(request, [content length]);
@@ -110,24 +112,22 @@
110 112
                 }
111 113
                 // otherwise convert it as BASE64 data string
112 114
                 else {
113
-                    // the body is BASE64 encoded string
114
-                    if(([mheaders valueForKey:@"content-type"] == nil && [mheaders valueForKey:@"Content-Type"] == nil) ||
115
-                       ([[[mheaders valueForKey:@"content-type"] lowercaseString] isEqualToString:@"application/octet-stream"] ||
116
-                        [[[mheaders valueForKey:@"Content-Type"] lowercaseString] isEqualToString:@"application/octet-stream"]))
115
+                    
116
+                    NSString * cType = [[self class]getHeaderIgnoreCases:@"content-type" fromHeaders:mheaders];
117
+                    // when content-type is application/octet* decode body string using BASE64 decoder
118
+                    if([[cType lowercaseString] hasPrefix:@"application/octet"])
117 119
                     {
118 120
                         blobData = [[NSData alloc] initWithBase64EncodedString:body options:0];
119
-                        [mheaders setValue:@"application/octet-stream" forKey:@"Content-Type"];
120 121
                         [request setHTTPBody:blobData];
121 122
                         size = [blobData length];
122 123
                     }
123
-                    // use the body string as is
124
+                    // otherwise use the body as-is
124 125
                     else
125 126
                     {
126 127
                         size = [body length];
127 128
                         [request setHTTPBody: [body dataUsingEncoding:NSUTF8StringEncoding]];
128 129
                     }
129 130
                 }
130
-                
131 131
             }
132 132
         }
133 133
 
@@ -138,21 +138,6 @@
138 138
     });
139 139
 }
140 140
 
141
-//+(void) buildEncodedRequest:(NSDictionary *)options
142
-//                   taskId:(NSString *)taskId
143
-//                   method:(NSString *)method
144
-//                      url:(NSString *)url
145
-//                  headers:(NSDictionary *)headers
146
-//                     body:(NSString *)body
147
-//               onComplete:(void(^)(NSURLRequest * req, long bodyLength))onComplete
148
-//{
149
-//	NSMutableData * formData = [[NSMutableData alloc] init];
150
-//    
151
-//	[formData appendData:[[NSString stringWithFormat:@"%@", body] dataUsingEncoding:NSUTF8StringEncoding]];
152
-//	onComplete(formData);
153
-//}
154
-
155
-
156 141
 +(void) buildFormBody:(NSArray *)form boundary:(NSString *)boundary onComplete:(void(^)(NSData * formData))onComplete
157 142
 {
158 143
     NSMutableData * formData = [[NSMutableData alloc] init];
@@ -225,5 +210,16 @@
225 210
     }
226 211
 }
227 212
 
213
++(NSString *) getHeaderIgnoreCases:(NSString *)field fromHeaders:(NSMutableArray *) headers {
214
+    
215
+    NSString * normalCase = [headers valueForKey:field];
216
+    NSString * ignoredCase = [headers valueForKey:[field lowercaseString]];
217
+    if( normalCase != nil)
218
+        return normalCase;
219
+    else
220
+        return ignoredCase;
221
+    
222
+}
223
+
228 224
 
229 225
 @end

+ 59
- 80
src/polyfill/Blob.js 파일 보기

@@ -25,7 +25,7 @@ export default class Blob {
25 25
 
26 26
   _ref:string = null;
27 27
   _blobCreated:boolean = false;
28
-  _onCreated:() => void;
28
+  _onCreated:Array<any> = [];
29 29
 
30 30
   static Instances:any = {}
31 31
 
@@ -35,86 +35,44 @@ export default class Blob {
35 35
     this.cacheName = getBlobName()
36 36
     this.isRNFetchBlobPolyfill = true
37 37
     this.type = mime
38
-    log.verbose('Blob constructor called' , data, 'mime', mime)
39
-
40
-    if(typeof data === 'string') {
41
-      // content from file
42
-      if(data.startsWith('RNFetchBlob-file://')) {
43
-        this._ref = data
44
-        this._blobCreated = true
45
-        if(typeof this._onCreated === 'function')
46
-          this._onCreated(this)
47
-      }
48
-      // content from variable need create file
49
-      else {
50
-        log.verbose('create Blob cache file ..')
51
-        this._ref = RNFetchBlob.wrap(blobCacheDir + this.cacheName)
52
-        let encoding = 'utf8'
53
-        if(typeof data === 'string' && String(mime).match('application/octet') )
54
-          encoding = 'base64'
55
-        else if(Array.isArray(data))
56
-          encoding = 'ascii'
57
-
58
-        this.init(data, encoding)
59
-            .then(() => {
60
-              log.verbose('init executed ')
61
-              if(typeof this._onCreated === 'function')
62
-                this._onCreated(this)
63
-            })
64
-            .catch((err) => {
65
-              log.error('RNFetchBlob cannot create Blob', err)
66
-            })
67
-      }
38
+    log.verbose('Blob constructor called', 'mime', mime)
39
+    this._ref = blobCacheDir + this.cacheName
40
+    let p = null
41
+    // content from file
42
+    if(typeof data === 'string' && data.startsWith('RNFetchBlob-file://')) {
43
+      log.verbose('create Blob cache file from file path')
44
+      this._ref = data
45
+      p = Promise.resolve()
68 46
     }
69
-    // TODO : handle mixed blob array
47
+    // content from variable need create file
48
+    else if(typeof data === 'string') {
49
+      log.verbose('create Blob cache file from string')
50
+      let encoding = 'utf8'
51
+      if(String(mime).match('application/octet'))
52
+        encoding = 'base64'
53
+      else if(Array.isArray(data))
54
+        encoding = 'ascii'
55
+      // create cache file
56
+      p = fs.writeFile(this._ref, data, encoding)
57
+
58
+    }
59
+    // when input is an array of mixed data types, create a file cache
70 60
     else if(Array.isArray(data)) {
71
-      this._ref = RNFetchBlob.wrap(blobCacheDir + this.cacheName)
72
-      createMixedBlobData(this._ref, data)
73
-        .then(() => {
74
-          if(typeof this._onCreated === 'function')
75
-            this._onCreated(this)
76
-        })
61
+      log.verbose('create Blob cache file from mixed array', data)
62
+      p = createMixedBlobData(this._ref, data)
77 63
     }
64
+    p && p.then(() => {
65
+      this._invokeOnCreateEvent()
66
+    })
67
+    .catch((err) => {
68
+      log.error('RNFetchBlob cannot create Blob : '+ this._ref)
69
+    })
78 70
 
79 71
   }
80 72
 
81 73
   onCreated(fn:() => void) {
82
-    log.verbose('register blob onCreated')
83
-    if(this._blobCreated)
84
-      fn()
85
-    else
86
-      this._onCreated = fn
87
-  }
88
-
89
-  /**
90
-   * Create blob file cache
91
-   * @nonstandard
92
-   * @param  {string | Array} data Data to create Blob file
93
-   * @param  {'base64' | 'utf8' | 'ascii'} encoding RNFetchBlob fs encoding
94
-   * @return {Promise}
95
-   */
96
-  init(data, encoding):Promise {
97
-    return new Promise((resolve, reject) => {
98
-      fs.exists(blobCacheDir)
99
-        .then((exist) => {
100
-          log.verbose('blob cache folder exist', blobCacheDir, exist)
101
-          let path = String(this._ref).replace('RNFetchBlob-file://', '')
102
-          log.verbose('create cache file', path)
103
-          if(!exist)
104
-            return fs.mkdir(blobCacheDir)
105
-                     .then(() => fs.createFile(path, data, encoding))
106
-          else
107
-            return fs.createFile(path, data, encoding)
108
-        })
109
-        .then(() => {
110
-          this._blobCreated = true
111
-          resolve()
112
-        })
113
-        .catch((err) => {
114
-          reject(err)
115
-        })
116
-    })
117
-
74
+    log.verbose('register blob onCreated', this._onCreated.length)
75
+    this._onCreated.push(fn)
118 76
   }
119 77
 
120 78
   /**
@@ -146,6 +104,21 @@ export default class Blob {
146 104
     return fs.unlink(this._ref)
147 105
   }
148 106
 
107
+  clearCache() {
108
+
109
+  }
110
+
111
+  _invokeOnCreateEvent() {
112
+    log.verbose('invoke create event')
113
+    this._blobCreated = true
114
+    let fns = this._onCreated
115
+    for(let i in fns) {
116
+      if(typeof fns[i] === 'function')
117
+        fns[i](this)
118
+    }
119
+    delete this._onCreated
120
+  }
121
+
149 122
 }
150 123
 
151 124
 /**
@@ -164,15 +137,21 @@ function getBlobName() {
164 137
  * @return {Promise}
165 138
  */
166 139
 function createMixedBlobData(ref, dataArray) {
167
-  let p = fs.createFile(ref, '')
140
+  let p = fs.writeFile(ref, '')
141
+  let args = []
168 142
   for(let i in dataArray) {
169 143
     let part = dataArray[i]
170 144
     if(part instanceof Blob)
171
-      p.then(() => fs.appendFile(ref, part.getRNFetchBlobRef()), 'uri')
145
+      args.push([ref, part.getRNFetchBlobRef(), 'uri'])
146
+    else if(typeof part === 'string')
147
+      args.push([ref, part, 'utf8'])
172 148
     else if (Array.isArray(part))
173
-      p.then(() => fs.appendFile(ref), part, 'ascii')
174
-    else
175
-      p.then(() => fs.appendFile(ref), part, 'utf8')
149
+      args.push([ref, part, 'ascii'])
176 150
   }
177
-  return p
151
+  return p.then(() => {
152
+    let promises = args.map((p) => {
153
+      return fs.appendFile.call(this, ...p)
154
+    })
155
+    return Promise.all(promises)
156
+  })
178 157
 }

+ 4
- 3
src/polyfill/XMLHttpRequest.js 파일 보기

@@ -92,8 +92,9 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
92 92
 
93 93
     this._upload = new XMLHttpRequestEventTarget()
94 94
     log.verbose(typeof body, body instanceof FormData)
95
-    if(Array.isArray(body)) {
96
-      // TODO
95
+
96
+    if(body instanceof Blob) {
97
+      body = RNFetchBlob.wrap(body.getRNFetchBlobRef())
97 98
     }
98 99
 
99 100
     this.dispatchEvent('loadstart')
@@ -211,7 +212,7 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
211 212
   }
212 213
 
213 214
   _onDone(resp) {
214
-    log.verbose('XMLHttpRequest done', resp.text())
215
+    log.verbose('XMLHttpRequest done', this)
215 216
     this.statusText = '200 OK'
216 217
     this._status = 200
217 218
     switch(resp.type) {