@hxa-rn/rn-fetch-blob 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +290 -0
- package/harmony/fetch_blob/LICENSE +21 -0
- package/harmony/fetch_blob/NOTICE +33 -0
- package/harmony/fetch_blob/OAT.xml +38 -0
- package/harmony/fetch_blob/build-profile.json5 +16 -0
- package/harmony/fetch_blob/hvigorfile.ts +2 -0
- package/harmony/fetch_blob/index.ets +1 -0
- package/harmony/fetch_blob/oh-package.json5 +14 -0
- package/harmony/fetch_blob/src/main/cpp/CMakeLists.txt +15 -0
- package/harmony/fetch_blob/src/main/cpp/FetchBlobPackage.h +13 -0
- package/harmony/fetch_blob/src/main/cpp/generated/RNOH/generated/BaseFetchBlobPackage.h +72 -0
- package/harmony/fetch_blob/src/main/cpp/generated/RNOH/generated/turbo_modules/RNFetchBlob.cpp +55 -0
- package/harmony/fetch_blob/src/main/cpp/generated/RNOH/generated/turbo_modules/RNFetchBlob.h +16 -0
- package/harmony/fetch_blob/src/main/ets/FetchBlobTurboModulesFactory.ets +18 -0
- package/harmony/fetch_blob/src/main/ets/Logger.ts +40 -0
- package/harmony/fetch_blob/src/main/ets/RNFetchBlobConfig.ts +45 -0
- package/harmony/fetch_blob/src/main/ets/RNFetchBlobFS.ts +673 -0
- package/harmony/fetch_blob/src/main/ets/RNFetchBlobImpl.ts +246 -0
- package/harmony/fetch_blob/src/main/ets/RNFetchBlobReq.ts +530 -0
- package/harmony/fetch_blob/src/main/ets/RNFetchBlobStream.ts +169 -0
- package/harmony/fetch_blob/src/main/ets/RNFetchBlobTurboModule.ts +192 -0
- package/harmony/fetch_blob/src/main/ets/generated/index.ets +5 -0
- package/harmony/fetch_blob/src/main/ets/generated/ts.ts +5 -0
- package/harmony/fetch_blob/src/main/ets/generated/turboModules/RNFetchBlob.ts +92 -0
- package/harmony/fetch_blob/src/main/ets/generated/turboModules/ts.ts +5 -0
- package/harmony/fetch_blob/src/main/module.json5 +22 -0
- package/harmony/fetch_blob/src/main/resources/base/element/string.json +8 -0
- package/harmony/fetch_blob/src/main/resources/en_US/element/string.json +8 -0
- package/harmony/fetch_blob/src/main/resources/zh_CN/element/string.json +8 -0
- package/harmony/fetch_blob.har +0 -0
- package/package.json +59 -0
- package/src/android.js +62 -0
- package/src/class/RNFetchBlobFile.js +17 -0
- package/src/class/RNFetchBlobReadStream.js +82 -0
- package/src/class/RNFetchBlobSession.js +74 -0
- package/src/class/RNFetchBlobWriteStream.js +57 -0
- package/src/class/StatefulPromise.js +7 -0
- package/src/fs.js +432 -0
- package/src/index.d.ts +690 -0
- package/src/index.js +577 -0
- package/src/ios.js +54 -0
- package/src/json-stream.js +45 -0
- package/src/lib/oboe-browser.min.js +1 -0
- package/src/polyfill/Blob.js +362 -0
- package/src/polyfill/Event.js +11 -0
- package/src/polyfill/EventTarget.js +79 -0
- package/src/polyfill/Fetch.js +213 -0
- package/src/polyfill/File.js +27 -0
- package/src/polyfill/FileReader.js +90 -0
- package/src/polyfill/ProgressEvent.js +32 -0
- package/src/polyfill/XMLHttpRequest.js +446 -0
- package/src/polyfill/XMLHttpRequestEventTarget.js +118 -0
- package/src/polyfill/index.js +11 -0
- package/src/specs/v1/NativeRNFetchBlob.ts +85 -0
- package/src/types.js +64 -0
- package/src/utils/log.js +40 -0
- package/src/utils/unicode.js +7 -0
- package/src/utils/uri.js +28 -0
- package/src/utils/uuid.js +4 -0
|
@@ -0,0 +1,27 @@
|
|
|
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 Blob from './Blob.js'
|
|
6
|
+
|
|
7
|
+
export default class File extends Blob {
|
|
8
|
+
|
|
9
|
+
name : string = '';
|
|
10
|
+
|
|
11
|
+
static build(name:string, data:any, cType:string):Promise<File> {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
if (data === undefined) {
|
|
14
|
+
reject(new TypeError('data is undefined'))
|
|
15
|
+
}
|
|
16
|
+
new File(data, cType).onCreated((f) => {
|
|
17
|
+
f.name = name
|
|
18
|
+
resolve(f)
|
|
19
|
+
})
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
constructor(data:any , cType:string) {
|
|
24
|
+
super(data, cType)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
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 ProgressEvent from './ProgressEvent.js'
|
|
6
|
+
import EventTarget from './EventTarget'
|
|
7
|
+
import Blob from './Blob'
|
|
8
|
+
import Log from '../utils/log.js'
|
|
9
|
+
import fs from '../fs'
|
|
10
|
+
|
|
11
|
+
const log = new Log('FileReader')
|
|
12
|
+
|
|
13
|
+
log.level(3)
|
|
14
|
+
|
|
15
|
+
export default class FileReader extends EventTarget {
|
|
16
|
+
|
|
17
|
+
static get EMPTY(){
|
|
18
|
+
return 0
|
|
19
|
+
}
|
|
20
|
+
static get LOADING(){
|
|
21
|
+
return 1
|
|
22
|
+
}
|
|
23
|
+
static get DONE(){
|
|
24
|
+
return 2
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// properties
|
|
28
|
+
_readState:number = 0;
|
|
29
|
+
_result:any;
|
|
30
|
+
_error:any;
|
|
31
|
+
|
|
32
|
+
get isRNFBPolyFill(){ return true }
|
|
33
|
+
|
|
34
|
+
// event handlers
|
|
35
|
+
onloadstart:(e:Event) => void;
|
|
36
|
+
onprogress:(e:Event) => void;
|
|
37
|
+
onload:(e:Event) => void;
|
|
38
|
+
onabort:(e:Event) => void;
|
|
39
|
+
onerror:(e:Event) => void;
|
|
40
|
+
onloadend:(e:Event) => void;
|
|
41
|
+
|
|
42
|
+
constructor() {
|
|
43
|
+
super()
|
|
44
|
+
log.verbose('file reader const')
|
|
45
|
+
this._result = null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
abort() {
|
|
49
|
+
log.verbose('abort')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
readAsArrayBuffer(b:Blob) {
|
|
53
|
+
log.verbose('readAsArrayBuffer', b)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
readAsBinaryString(b:Blob) {
|
|
57
|
+
log.verbose('readAsBinaryString', b)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
readAsText(b:Blob, label:?string) {
|
|
61
|
+
log.verbose('readAsText', b, label)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
readAsDataURL(b:Blob) {
|
|
65
|
+
log.verbose('readAsDataURL', b)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
dispatchEvent(event, e) {
|
|
69
|
+
log.verbose('dispatch event', event, e)
|
|
70
|
+
super.dispatchEvent(event, e)
|
|
71
|
+
if(typeof this[`on${event}`] === 'function') {
|
|
72
|
+
this[`on${event}`](e)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// private methods
|
|
77
|
+
|
|
78
|
+
// getters and setters
|
|
79
|
+
|
|
80
|
+
get readyState() {
|
|
81
|
+
return this._readyState
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get result() {
|
|
85
|
+
return this._result
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
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 Event from './Event'
|
|
6
|
+
|
|
7
|
+
export default class ProgressEvent extends Event {
|
|
8
|
+
|
|
9
|
+
_lengthComputable : boolean = false;
|
|
10
|
+
_loaded : number = -1;
|
|
11
|
+
_total : numver = -1;
|
|
12
|
+
|
|
13
|
+
constructor(lengthComputable, loaded, total) {
|
|
14
|
+
super()
|
|
15
|
+
this._lengthComputable = lengthComputable;
|
|
16
|
+
this._loaded = loaded
|
|
17
|
+
this._total = total
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get lengthComputable() {
|
|
21
|
+
return this._lengthComputable
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get loaded() {
|
|
25
|
+
return this._loaded
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get total() {
|
|
29
|
+
return this._total
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
}
|
|
@@ -0,0 +1,446 @@
|
|
|
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 XMLHttpRequestEventTarget from './XMLHttpRequestEventTarget.js'
|
|
7
|
+
import Log from '../utils/log.js'
|
|
8
|
+
import Blob from './Blob.js'
|
|
9
|
+
import ProgressEvent from './ProgressEvent.js'
|
|
10
|
+
import URIUtil from '../utils/uri'
|
|
11
|
+
|
|
12
|
+
const log = new Log('XMLHttpRequest')
|
|
13
|
+
|
|
14
|
+
log.disable()
|
|
15
|
+
// log.level(3)
|
|
16
|
+
|
|
17
|
+
const UNSENT = 0
|
|
18
|
+
const OPENED = 1
|
|
19
|
+
const HEADERS_RECEIVED = 2
|
|
20
|
+
const LOADING = 3
|
|
21
|
+
const DONE = 4
|
|
22
|
+
|
|
23
|
+
export default class XMLHttpRequest extends XMLHttpRequestEventTarget{
|
|
24
|
+
|
|
25
|
+
_onreadystatechange : () => void;
|
|
26
|
+
|
|
27
|
+
upload : XMLHttpRequestEventTarget = new XMLHttpRequestEventTarget();
|
|
28
|
+
static binaryContentTypes : Array<string> = [
|
|
29
|
+
'image/', 'video/', 'audio/'
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// readonly
|
|
33
|
+
_readyState : number = UNSENT;
|
|
34
|
+
_uriType : 'net' | 'file' = 'net';
|
|
35
|
+
_response : any = '';
|
|
36
|
+
_responseText : any = '';
|
|
37
|
+
_responseHeaders : any = {};
|
|
38
|
+
_responseType : '' | 'arraybuffer' | 'blob' | 'json' | 'text' = '';
|
|
39
|
+
// TODO : not suppoted ATM
|
|
40
|
+
_responseURL : null = '';
|
|
41
|
+
_responseXML : null = '';
|
|
42
|
+
_status : number = 0;
|
|
43
|
+
_statusText : string = '';
|
|
44
|
+
_timeout : number = 60000;
|
|
45
|
+
_sendFlag : boolean = false;
|
|
46
|
+
_uploadStarted : boolean = false;
|
|
47
|
+
_increment : boolean = false;
|
|
48
|
+
|
|
49
|
+
// RNFetchBlob compatible data structure
|
|
50
|
+
_config : RNFetchBlobConfig = {};
|
|
51
|
+
_url : any;
|
|
52
|
+
_method : string;
|
|
53
|
+
_headers: any = {
|
|
54
|
+
'Content-Type' : 'text/plain'
|
|
55
|
+
};
|
|
56
|
+
_cleanUp : () => void = null;
|
|
57
|
+
_body: any;
|
|
58
|
+
|
|
59
|
+
// RNFetchBlob promise object, which has `progress`, `uploadProgress`, and
|
|
60
|
+
// `cancel` methods.
|
|
61
|
+
_task: any;
|
|
62
|
+
|
|
63
|
+
// constants
|
|
64
|
+
get UNSENT() { return UNSENT }
|
|
65
|
+
get OPENED() { return OPENED }
|
|
66
|
+
get HEADERS_RECEIVED() { return HEADERS_RECEIVED }
|
|
67
|
+
get LOADING() { return LOADING }
|
|
68
|
+
get DONE() { return DONE }
|
|
69
|
+
|
|
70
|
+
static get UNSENT() {
|
|
71
|
+
return UNSENT
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static get OPENED() {
|
|
75
|
+
return OPENED
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static get HEADERS_RECEIVED() {
|
|
79
|
+
return HEADERS_RECEIVED
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static get LOADING() {
|
|
83
|
+
return LOADING
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static get DONE() {
|
|
87
|
+
return DONE
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static setLog(level:number) {
|
|
91
|
+
if(level === -1)
|
|
92
|
+
log.disable()
|
|
93
|
+
else
|
|
94
|
+
log.level(level)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static addBinaryContentType(substr:string) {
|
|
98
|
+
for(let i in XMLHttpRequest.binaryContentTypes) {
|
|
99
|
+
if(new RegExp(substr,'i').test(XMLHttpRequest.binaryContentTypes[i])) {
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
XMLHttpRequest.binaryContentTypes.push(substr)
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static removeBinaryContentType(val) {
|
|
108
|
+
for(let i in XMLHttpRequest.binaryContentTypes) {
|
|
109
|
+
if(new RegExp(substr,'i').test(XMLHttpRequest.binaryContentTypes[i])) {
|
|
110
|
+
XMLHttpRequest.binaryContentTypes.splice(i,1)
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
constructor() {
|
|
117
|
+
log.verbose('XMLHttpRequest constructor called')
|
|
118
|
+
super()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* XMLHttpRequest.open, always async, user and password not supported. When
|
|
124
|
+
* this method invoked, headers should becomes empty again.
|
|
125
|
+
* @param {string} method Request method
|
|
126
|
+
* @param {string} url Request URL
|
|
127
|
+
* @param {true} async Always async
|
|
128
|
+
* @param {any} user NOT SUPPORTED
|
|
129
|
+
* @param {any} password NOT SUPPORTED
|
|
130
|
+
*/
|
|
131
|
+
open(method:string, url:string, async:true, user:any, password:any) {
|
|
132
|
+
log.verbose('XMLHttpRequest open ', method, url, async, user, password)
|
|
133
|
+
this._method = method
|
|
134
|
+
this._url = url
|
|
135
|
+
this._headers = {}
|
|
136
|
+
this._increment = URIUtil.isJSONStreamURI(this._url)
|
|
137
|
+
this._url = this._url.replace(/^JSONStream\:\/\//, '')
|
|
138
|
+
this._dispatchReadStateChange(XMLHttpRequest.OPENED)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Invoke this function to send HTTP request, and set body.
|
|
143
|
+
* @param {any} body Body in RNfetchblob flavor
|
|
144
|
+
*/
|
|
145
|
+
send(body) {
|
|
146
|
+
|
|
147
|
+
this._body = body
|
|
148
|
+
|
|
149
|
+
if(this._readyState !== XMLHttpRequest.OPENED)
|
|
150
|
+
throw 'InvalidStateError : XMLHttpRequest is not opened yet.'
|
|
151
|
+
let promise = Promise.resolve()
|
|
152
|
+
this._sendFlag = true
|
|
153
|
+
log.verbose('XMLHttpRequest send ', body)
|
|
154
|
+
let {_method, _url, _headers } = this
|
|
155
|
+
log.verbose('sending request with args', _method, _url, _headers, body)
|
|
156
|
+
log.verbose(typeof body, body instanceof FormData)
|
|
157
|
+
|
|
158
|
+
if(body instanceof Blob) {
|
|
159
|
+
log.debug('sending blob body', body._blobCreated)
|
|
160
|
+
promise = new Promise((resolve, reject) => {
|
|
161
|
+
body.onCreated((blob) => {
|
|
162
|
+
// when the blob is derived (not created by RN developer), the blob
|
|
163
|
+
// will be released after XMLHttpRequest sent
|
|
164
|
+
if(blob.isDerived) {
|
|
165
|
+
this._cleanUp = () => {
|
|
166
|
+
blob.close()
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
log.debug('body created send request')
|
|
170
|
+
body = RNFetchBlob.wrap(blob.getRNFetchBlobRef())
|
|
171
|
+
resolve()
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
else if(typeof body === 'object') {
|
|
176
|
+
body = JSON.stringify(body)
|
|
177
|
+
promise = Promise.resolve()
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
body = body ? body.toString() : body
|
|
181
|
+
promise = Promise.resolve()
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
promise.then(() => {
|
|
185
|
+
log.debug('send request invoke', body)
|
|
186
|
+
for(let h in _headers) {
|
|
187
|
+
_headers[h] = _headers[h].toString()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this._task = RNFetchBlob
|
|
191
|
+
.config({
|
|
192
|
+
auto: true,
|
|
193
|
+
timeout : this._timeout,
|
|
194
|
+
increment : this._increment,
|
|
195
|
+
binaryContentTypes : XMLHttpRequest.binaryContentTypes
|
|
196
|
+
})
|
|
197
|
+
.fetch(_method, _url, _headers, body)
|
|
198
|
+
this._task
|
|
199
|
+
.stateChange(this._headerReceived)
|
|
200
|
+
.uploadProgress(this._uploadProgressEvent)
|
|
201
|
+
.progress(this._progressEvent)
|
|
202
|
+
.catch(this._onError)
|
|
203
|
+
.then(this._onDone)
|
|
204
|
+
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
overrideMimeType(mime:string) {
|
|
209
|
+
log.verbose('XMLHttpRequest overrideMimeType', mime)
|
|
210
|
+
this._headers['Content-Type'] = mime
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
setRequestHeader(name, value) {
|
|
214
|
+
log.verbose('XMLHttpRequest set header', name, value)
|
|
215
|
+
if(this._readyState !== OPENED || this._sendFlag) {
|
|
216
|
+
throw `InvalidStateError : Calling setRequestHeader in wrong state ${this._readyState}`
|
|
217
|
+
}
|
|
218
|
+
// UNICODE SHOULD NOT PASS
|
|
219
|
+
if(typeof name !== 'string' || /[^\u0000-\u00ff]/.test(name)) {
|
|
220
|
+
throw 'TypeError : header field name should be a string'
|
|
221
|
+
}
|
|
222
|
+
//
|
|
223
|
+
let invalidPatterns = [
|
|
224
|
+
/[\(\)\>\<\@\,\:\\\/\[\]\?\=\}\{\s\ \u007f\;\t\0\v\r]/,
|
|
225
|
+
/tt/
|
|
226
|
+
]
|
|
227
|
+
for(let pattern of invalidPatterns) {
|
|
228
|
+
if(pattern.test(name) || typeof name !== 'string') {
|
|
229
|
+
throw `SyntaxError : Invalid header field name ${name}`
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
this._headers[name] = value
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
abort() {
|
|
236
|
+
log.verbose('XMLHttpRequest abort ')
|
|
237
|
+
if(!this._task)
|
|
238
|
+
return
|
|
239
|
+
this._task.cancel((err) => {
|
|
240
|
+
let e = {
|
|
241
|
+
timeStamp : Date.now(),
|
|
242
|
+
}
|
|
243
|
+
if(this.onabort)
|
|
244
|
+
this.onabort()
|
|
245
|
+
if(err) {
|
|
246
|
+
e.detail = err
|
|
247
|
+
e.type = 'error'
|
|
248
|
+
this.dispatchEvent('error', e)
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
e.type = 'abort'
|
|
252
|
+
this.dispatchEvent('abort', e)
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
getResponseHeader(field:string):string | null {
|
|
258
|
+
log.verbose('XMLHttpRequest get header', field, this._responseHeaders)
|
|
259
|
+
if(!this._responseHeaders)
|
|
260
|
+
return null
|
|
261
|
+
return (this._responseHeaders[field] || this._responseHeaders[field.toLowerCase()]) || null
|
|
262
|
+
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
getAllResponseHeaders():string | null {
|
|
266
|
+
log.verbose('XMLHttpRequest get all headers', this._responseHeaders)
|
|
267
|
+
if(!this._responseHeaders)
|
|
268
|
+
return ''
|
|
269
|
+
let result = ''
|
|
270
|
+
let respHeaders = this.responseHeaders
|
|
271
|
+
for(let i in respHeaders) {
|
|
272
|
+
result += `${i}: ${respHeaders[i]}${String.fromCharCode(0x0D,0x0A)}`
|
|
273
|
+
}
|
|
274
|
+
return result.substr(0, result.length-2)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
_headerReceived = (e) => {
|
|
278
|
+
log.debug('header received ', this._task.taskId, e)
|
|
279
|
+
this.responseURL = this._url
|
|
280
|
+
if(e.state === "2" && e.taskId === this._task.taskId) {
|
|
281
|
+
this._responseHeaders = e.headers
|
|
282
|
+
this._statusText = e.status
|
|
283
|
+
this._status = Math.floor(e.status)
|
|
284
|
+
this._dispatchReadStateChange(XMLHttpRequest.HEADERS_RECEIVED)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
_uploadProgressEvent = (send:number, total:number) => {
|
|
289
|
+
if(!this._uploadStarted) {
|
|
290
|
+
this.upload.dispatchEvent('loadstart')
|
|
291
|
+
this._uploadStarted = true
|
|
292
|
+
}
|
|
293
|
+
if(send >= total)
|
|
294
|
+
this.upload.dispatchEvent('load')
|
|
295
|
+
this.upload.dispatchEvent('progress', new ProgressEvent(true, send, total))
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
_progressEvent = (send:number, total:number, chunk:string) => {
|
|
299
|
+
log.verbose(this.readyState)
|
|
300
|
+
if(this._readyState === XMLHttpRequest.HEADERS_RECEIVED)
|
|
301
|
+
this._dispatchReadStateChange(XMLHttpRequest.LOADING)
|
|
302
|
+
let lengthComputable = false
|
|
303
|
+
if(total && total >= 0)
|
|
304
|
+
lengthComputable = true
|
|
305
|
+
let e = new ProgressEvent(lengthComputable, send, total)
|
|
306
|
+
|
|
307
|
+
if(this._increment) {
|
|
308
|
+
this._responseText += chunk
|
|
309
|
+
}
|
|
310
|
+
this.dispatchEvent('progress', e)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
_onError = (err) => {
|
|
314
|
+
let statusCode = Math.floor(this.status)
|
|
315
|
+
if(statusCode >= 100 && statusCode !== 408) {
|
|
316
|
+
return
|
|
317
|
+
}
|
|
318
|
+
log.debug('XMLHttpRequest error', err)
|
|
319
|
+
this._statusText = err
|
|
320
|
+
this._status = String(err).match(/\d+/)
|
|
321
|
+
this._status = this._status ? Math.floor(this.status) : 404
|
|
322
|
+
this._dispatchReadStateChange(XMLHttpRequest.DONE)
|
|
323
|
+
if(err && String(err.message).match(/(timed\sout|timedout)/) || this._status == 408) {
|
|
324
|
+
this.dispatchEvent('timeout')
|
|
325
|
+
}
|
|
326
|
+
this.dispatchEvent('loadend')
|
|
327
|
+
this.dispatchEvent('error', {
|
|
328
|
+
type : 'error',
|
|
329
|
+
detail : err
|
|
330
|
+
})
|
|
331
|
+
this.clearEventListeners()
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
_onDone = (resp) => {
|
|
335
|
+
log.debug('XMLHttpRequest done', this._url, resp, this)
|
|
336
|
+
this._statusText = this._status
|
|
337
|
+
let responseDataReady = () => {
|
|
338
|
+
log.debug('request done state = 4')
|
|
339
|
+
this.dispatchEvent('load')
|
|
340
|
+
this.dispatchEvent('loadend')
|
|
341
|
+
this._dispatchReadStateChange(XMLHttpRequest.DONE)
|
|
342
|
+
this.clearEventListeners()
|
|
343
|
+
}
|
|
344
|
+
if(resp) {
|
|
345
|
+
let info = resp.respInfo || {}
|
|
346
|
+
log.debug(this._url, info, info.respType)
|
|
347
|
+
switch(this._responseType) {
|
|
348
|
+
case 'blob' :
|
|
349
|
+
resp.blob().then((b) => {
|
|
350
|
+
this._responseText = resp.text()
|
|
351
|
+
this._response = b
|
|
352
|
+
responseDataReady()
|
|
353
|
+
})
|
|
354
|
+
break;
|
|
355
|
+
case 'arraybuffer':
|
|
356
|
+
// TODO : to array buffer
|
|
357
|
+
break
|
|
358
|
+
case 'json':
|
|
359
|
+
this._response = resp.json()
|
|
360
|
+
this._responseText = resp.text()
|
|
361
|
+
break
|
|
362
|
+
default :
|
|
363
|
+
this._responseText = resp.text()
|
|
364
|
+
this._response = this.responseText
|
|
365
|
+
responseDataReady()
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
_dispatchReadStateChange(state) {
|
|
373
|
+
this._readyState = state
|
|
374
|
+
if(typeof this._onreadystatechange === 'function')
|
|
375
|
+
this._onreadystatechange()
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
set onreadystatechange(fn:() => void) {
|
|
379
|
+
log.verbose('XMLHttpRequest set onreadystatechange', fn)
|
|
380
|
+
this._onreadystatechange = fn
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
get onreadystatechange() {
|
|
384
|
+
return this._onreadystatechange
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
get readyState() {
|
|
388
|
+
log.verbose('get readyState', this._readyState)
|
|
389
|
+
return this._readyState
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
get status() {
|
|
393
|
+
log.verbose('get status', this._status)
|
|
394
|
+
return this._status
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
get statusText() {
|
|
398
|
+
log.verbose('get statusText', this._statusText)
|
|
399
|
+
return this._statusText
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
get response() {
|
|
403
|
+
log.verbose('get response', this._response)
|
|
404
|
+
return this._response
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
get responseText() {
|
|
408
|
+
log.verbose('get responseText', this._responseText)
|
|
409
|
+
return this._responseText
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
get responseURL() {
|
|
413
|
+
log.verbose('get responseURL', this._responseURL)
|
|
414
|
+
return this._responseURL
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
get responseHeaders() {
|
|
418
|
+
log.verbose('get responseHeaders', this._responseHeaders)
|
|
419
|
+
return this._responseHeaders
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
set timeout(val) {
|
|
423
|
+
this._timeout = val*1000
|
|
424
|
+
log.verbose('set timeout', this._timeout)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
get timeout() {
|
|
428
|
+
log.verbose('get timeout', this._timeout)
|
|
429
|
+
return this._timeout
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
set responseType(val) {
|
|
433
|
+
log.verbose('set response type', this._responseType)
|
|
434
|
+
this._responseType = val
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
get responseType() {
|
|
438
|
+
log.verbose('get response type', this._responseType)
|
|
439
|
+
return this._responseType
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
static get isRNFBPolyfill() {
|
|
443
|
+
return true
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
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 EventTarget from './EventTarget.js'
|
|
6
|
+
import Log from '../utils/log.js'
|
|
7
|
+
|
|
8
|
+
const log = new Log('XMLHttpRequestEventTarget')
|
|
9
|
+
|
|
10
|
+
log.disable()
|
|
11
|
+
// log.level(3)
|
|
12
|
+
|
|
13
|
+
export default class XMLHttpRequestEventTarget extends EventTarget {
|
|
14
|
+
|
|
15
|
+
_onabort : (e:Event) => void = () => {};
|
|
16
|
+
_onerror : (e:Event) => void = () => {};
|
|
17
|
+
_onload : (e:Event) => void = () => {};
|
|
18
|
+
_onloadstart : (e:Event) => void = () => {};
|
|
19
|
+
_onprogress : (e:Event) => void = () => {};
|
|
20
|
+
_ontimeout : (e:Event) => void = () => {};
|
|
21
|
+
_onloadend : (e:Event) => void = () => {};
|
|
22
|
+
|
|
23
|
+
constructor() {
|
|
24
|
+
super()
|
|
25
|
+
log.info('constructor called')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
dispatchEvent(event:string, e:Event) {
|
|
29
|
+
log.debug('dispatch event', event, e)
|
|
30
|
+
super.dispatchEvent(event, e)
|
|
31
|
+
switch(event) {
|
|
32
|
+
case 'abort' :
|
|
33
|
+
this._onabort(e)
|
|
34
|
+
break;
|
|
35
|
+
case 'error' :
|
|
36
|
+
this._onerror(e)
|
|
37
|
+
break;
|
|
38
|
+
case 'load' :
|
|
39
|
+
this._onload(e)
|
|
40
|
+
break;
|
|
41
|
+
case 'loadstart' :
|
|
42
|
+
this._onloadstart(e)
|
|
43
|
+
break;
|
|
44
|
+
case 'loadend' :
|
|
45
|
+
this._onloadend(e)
|
|
46
|
+
break;
|
|
47
|
+
case 'progress' :
|
|
48
|
+
this._onprogress(e)
|
|
49
|
+
break;
|
|
50
|
+
case 'timeout' :
|
|
51
|
+
this._ontimeout(e)
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
set onabort(fn:(e:Event) => void) {
|
|
57
|
+
log.info('set onabort')
|
|
58
|
+
this._onabort = fn
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get onabort() {
|
|
62
|
+
return this._onabort
|
|
63
|
+
}
|
|
64
|
+
set onerror(fn:(e:Event) => void) {
|
|
65
|
+
log.info('set onerror')
|
|
66
|
+
this._onerror = fn
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get onerror() {
|
|
70
|
+
return this._onerror
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
set onload(fn:(e:Event) => void) {
|
|
74
|
+
log.info('set onload', fn)
|
|
75
|
+
this._onload = fn
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get onload() {
|
|
79
|
+
return this._onload
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
set onloadstart(fn:(e:Event) => void) {
|
|
83
|
+
log.info('set onloadstart')
|
|
84
|
+
this._onloadstart = fn
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get onloadstart() {
|
|
88
|
+
return this._onloadstart
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
set onprogress(fn:(e:Event) => void) {
|
|
92
|
+
log.info('set onprogress')
|
|
93
|
+
this._onprogress = fn
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get onprogress() {
|
|
97
|
+
return this._onprogress
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
set ontimeout(fn:(e:Event) => void) {
|
|
101
|
+
log.info('set ontimeout')
|
|
102
|
+
this._ontimeout = fn
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
get ontimeout() {
|
|
106
|
+
return this._ontimeout
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
set onloadend(fn:(e:Event) => void) {
|
|
110
|
+
log.info('set onloadend')
|
|
111
|
+
this._onloadend = fn
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get onloadend() {
|
|
115
|
+
return this._onloadend
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
}
|