Skip to content
This repository was archived by the owner on Mar 16, 2019. It is now read-only.

Commit 1e1a6b0

Browse files
committed
Fix unicode response issue
Fetch polyfill wip #70
1 parent 45ddccc commit 1e1a6b0

File tree

14 files changed

+336
-28
lines changed

14 files changed

+336
-28
lines changed

src/index.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ function fetch(...args:any):Promise {
112112
let taskId = getUUID()
113113
let options = this || {}
114114
let subscription, subscriptionUpload, stateEvent
115+
let respInfo = {}
115116

116117
let promise = new Promise((resolve, reject) => {
117118
let [method, url, headers, body] = [...args]
@@ -131,6 +132,7 @@ function fetch(...args:any):Promise {
131132
})
132133

133134
stateEvent = emitter.addListener('RNFetchBlobState', (e) => {
135+
respInfo = e
134136
if(e.taskId === taskId && promise.onStateChange) {
135137
promise.onStateChange(e)
136138
}
@@ -144,27 +146,26 @@ function fetch(...args:any):Promise {
144146

145147
let req = RNFetchBlob[nativeMethodName]
146148

147-
req(options, taskId, method, url, headers || {}, body, (err, info, data) => {
149+
req(options, taskId, method, url, headers || {}, body, (err, unsused, data) => {
148150

149151
// task done, remove event listener
150152
subscription.remove()
151153
subscriptionUpload.remove()
152154
stateEvent.remove()
153-
info = info ? info : {}
155+
154156
if(err)
155157
reject(new Error(err, info))
156158
else {
157159
let rnfbEncode = 'base64'
158160
// response data is saved to storage
159161
if(options.path || options.fileCache || options.addAndroidDownloads
160-
|| options.key || options.auto && info.respType === 'blob') {
162+
|| options.key || options.auto && respInfo.respType === 'blob') {
161163
rnfbEncode = 'path'
162164
if(options.session)
163165
session(options.session).add(data)
164166
}
165-
info = info || {}
166-
info.rnfbEncode = rnfbEncode
167-
resolve(new FetchBlobResponse(taskId, info, data))
167+
respInfo.rnfbEncode = rnfbEncode
168+
resolve(new FetchBlobResponse(taskId, respInfo, data))
168169
}
169170

170171
})
@@ -240,7 +241,6 @@ class FetchBlobResponse {
240241
try {
241242
let b = new polyfill.Blob(this.data, 'application/octet-stream;BASE64')
242243
b.onCreated(() => {
243-
console.log('####', b)
244244
resolve(b)
245245
})
246246
} catch(err) {
@@ -254,7 +254,7 @@ class FetchBlobResponse {
254254
* @return {string} Decoded base64 string.
255255
*/
256256
this.text = ():string => {
257-
return base64.decode(this.data)
257+
return decodeURIComponent(base64.decode(this.data))
258258
}
259259
/**
260260
* Convert result to JSON object.

src/ios/RNFetchBlobConst.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern NSString *const CONFIG_FILE_EXT;
2929
extern NSString *const CONFIG_TRUSTY;
3030
extern NSString *const CONFIG_INDICATOR;
3131
extern NSString *const CONFIG_KEY;
32+
extern NSString *const CONFIG_EXTRA_BLOB_CTYPE;
3233

3334
// fs events
3435
extern NSString *const FS_EVENT_DATA;

src/ios/RNFetchBlobConst.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
extern NSString *const CONFIG_TRUSTY = @"trusty";
2121
extern NSString *const CONFIG_INDICATOR = @"indicator";
2222
extern NSString *const CONFIG_KEY = @"key";
23+
extern NSString *const CONFIG_EXTRA_BLOB_CTYPE = @"binaryContentTypes";
2324

2425
extern NSString *const EVENT_STATE_CHANGE = @"RNFetchBlobState";
2526
extern NSString *const MSG_EVENT = @"RNFetchBlobMessage";

src/ios/RNFetchBlobFS.m

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString
234234
return;
235235
}
236236
else {
237-
content = [data dataUsingEncoding:NSISOLatin1StringEncoding];
237+
content = [data dataUsingEncoding:NSUTF8StringEncoding];
238238
}
239239
if(append == YES) {
240240
[fileHandle seekToEndOfFile];
@@ -333,8 +333,13 @@ + (void) readFile:(NSString *)path encoding:(NSString *)encoding
333333
onComplete(fileContent);
334334

335335
if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
336-
if(resolve != nil)
337-
resolve([[NSString alloc] initWithData:fileContent encoding:NSUTF8StringEncoding]);
336+
if(resolve != nil) {
337+
NSString * utf8 = [[NSString alloc] initWithData:fileContent encoding:NSUTF8StringEncoding];
338+
if(utf8 == nil)
339+
resolve([[NSString alloc] initWithData:fileContent encoding:NSISOLatin1StringEncoding]);
340+
else
341+
resolve(utf8);
342+
}
338343
}
339344
else if ([[encoding lowercaseString] isEqualToString:@"base64"]) {
340345
if(resolve != nil)

src/ios/RNFetchBlobNetwork.m

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,21 @@ - (void) URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dat
201201
lowercaseString];
202202
if([headers valueForKey:@"Content-Type"] != nil)
203203
{
204-
if([respType containsString:@"text/"])
204+
NSArray * extraBlobCTypes = [options objectForKey:CONFIG_EXTRA_BLOB_CTYPE];
205+
// If extra blob content type is not empty, check if response type matches
206+
if( extraBlobCTypes != nil) {
207+
for(NSString * substr in extraBlobCTypes)
208+
{
209+
if([[respType lowercaseString] containsString:[substr lowercaseString]])
210+
{
211+
respType = @"blob";
212+
respFile = YES;
213+
destPath = [RNFetchBlobFS getTempPath:taskId withExtension:nil];
214+
break;
215+
}
216+
}
217+
}
218+
else if([respType containsString:@"text/"])
205219
{
206220
respType = @"text";
207221
}
@@ -315,11 +329,17 @@ - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCom
315329
}
316330
// base64 response
317331
else {
318-
NSString * res = [[NSString alloc] initWithData:respData encoding:NSUTF8StringEncoding];
332+
NSString * utf8 = [[[NSString alloc] initWithData:respData encoding:NSUTF8StringEncoding] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
333+
NSString * base64 = @"";
334+
if(utf8 != nil)
335+
base64 = [[utf8 dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
336+
else
337+
base64 = [respData base64EncodedStringWithOptions:0];
319338
callback(@[error == nil ? [NSNull null] : [error localizedDescription],
320339
respInfo == nil ? [NSNull null] : respInfo,
321-
[respData base64EncodedStringWithOptions:0]
322-
]);
340+
base64
341+
]);
342+
323343
}
324344

325345
[taskTable removeObjectForKey:taskId];

src/polyfill/Fetch.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import RNFetchBlob from '../index.js'
2+
import Log from '../utils/log.js'
3+
import fs from '../fs'
4+
import unicode from '../utils/unicode'
5+
6+
const log = new Log('FetchPolyfill')
7+
8+
log.level(3)
9+
10+
11+
export default class Fetch {
12+
13+
provider:RNFetchBlobFetch;
14+
15+
constructor(config:RNFetchBlobConfig) {
16+
this.provider = new RNFetchBlobFetch(config)
17+
}
18+
19+
}
20+
21+
class RNFetchBlobFetch {
22+
23+
constructor(config:RNFetchBlobConfig) {
24+
this._fetch = (url, options) => {
25+
let bodyUsed = false
26+
options.headers = options.headers || {}
27+
options['Content-Type'] = options.headers['Content-Type'] || options.headers['content-type']
28+
options['content-type'] = options.headers['Content-Type'] || options.headers['content-type']
29+
return RNFetchBlob.config(config)
30+
.fetch(options.method, url, options.headers, options.body)
31+
.then((resp) => {
32+
let info = resp.info()
33+
return Promise.resolve({
34+
headers : info.headers,
35+
ok : info.status >= 200 && info.status <= 299,
36+
status : info.status,
37+
type : 'basic',
38+
bodyUsed,
39+
arrayBuffer : () => {
40+
log.verbose('to arrayBuffer', info)
41+
42+
},
43+
text : () => {
44+
log.verbose('to text', resp, info)
45+
switch (info.rnfbEncode) {
46+
case 'base64':
47+
let result = unicode(resp.text())
48+
return Promise.resolve(result)
49+
break
50+
case 'path':
51+
return resp.readFile('utf8').then((data) => {
52+
data = unicode(data)
53+
return Promise.resolve(data)
54+
})
55+
break
56+
case '':
57+
default:
58+
return Promise.resolve(resp.data)
59+
break
60+
}
61+
},
62+
json : () => {
63+
log.verbose('to json', resp, info)
64+
switch (info.rnfbEncode) {
65+
case 'base64':
66+
return Promise.resolve(resp.json())
67+
case 'path':
68+
return resp.readFile('utf8').then((data) => {
69+
return Promise.resolve(JSON.parse(data))
70+
})
71+
case '':
72+
default:
73+
return Promise.resolve(JSON.parse(resp.data))
74+
}
75+
},
76+
formData : () => {
77+
log.verbose('to formData', resp, info)
78+
79+
}
80+
})
81+
})
82+
}
83+
}
84+
85+
get fetch() {
86+
return this._fetch
87+
}
88+
89+
}

src/polyfill/FileReader.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2016 wkh237@github. All rights reserved.
2+
// Use of this source code is governed by a MIT-style license that can be
3+
// found in the LICENSE file.
4+
5+
import RNFetchBlob from '../index.js'
6+
import ProgressEvent from './ProgressEvent.js'
7+
import EventTarget from './EventTarget'
8+
import Blob from './Blob'
9+
import Log from '../utils/log.js'
10+
import fs from '../fs'
11+
12+
const log = new Log('FileReader')
13+
14+
log.level(3)
15+
16+
export default class FileReader extends EventTarget {
17+
18+
static get EMPTY(){
19+
return 0
20+
}
21+
static get LOADING(){
22+
return 1
23+
}
24+
static get DONE(){
25+
return 2
26+
}
27+
28+
// properties
29+
_readState:number = 0;
30+
_result:any;
31+
_error:any;
32+
33+
get isRNFBPolyFill(){ return true }
34+
35+
// event handlers
36+
onloadstart:(e:Event) => void;
37+
onprogress:(e:Event) => void;
38+
onload:(e:Event) => void;
39+
onabort:(e:Event) => void;
40+
onerror:(e:Event) => void;
41+
onloadend:(e:Event) => void;
42+
43+
constructor() {
44+
super()
45+
log.verbose('file reader const')
46+
this._result = null
47+
}
48+
49+
abort() {
50+
log.verbose('abort', b, label)
51+
}
52+
53+
readAsArrayBuffer(b:Blob) {
54+
log.verbose('readAsArrayBuffer', b, label)
55+
}
56+
57+
readAsBinaryString(b:Blob) {
58+
log.verbose('readAsBinaryString', b, label)
59+
}
60+
61+
readAsText(b:Blob, label:?string) {
62+
log.verbose('readAsText', b, label)
63+
}
64+
65+
readAsDataURL(b:Blob) {
66+
log.verbose('readAsDataURL', b, label)
67+
}
68+
69+
dispatchEvent(event, e) {
70+
log.verbose('dispatch event', event, e)
71+
super.dispatchEvent(event, e)
72+
if(typeof this[`on${event}`] === 'function') {
73+
this[`on${event}`](e)
74+
}
75+
}
76+
77+
// private methods
78+
79+
// getters and setters
80+
81+
get readState() {
82+
return this._readyState
83+
}
84+
85+
get result() {
86+
return this._result
87+
}
88+
89+
90+
91+
}

0 commit comments

Comments
 (0)