index.uts 10.8 KB
Newer Older
DCloud-yyl's avatar
DCloud-yyl 已提交
1
import { Request, RequestOptions, RequestSuccess, RequestFail, RequestTask, UploadFileOptions, UploadFile, UploadTask, OnProgressUpdateResult, UploadFileSuccess, UploadFileProgressUpdateCallback, DownloadFileProgressUpdateCallback, DownloadFileOptions, OnProgressDownloadResult, DownloadFile ,DownloadFileSuccess} from './interface';
DCloud-yyl's avatar
DCloud-yyl 已提交
2 3
import { NetworkManager, NetworkRequestListener, NetworkUploadFileListener, NetworkDownloadFileListener } from './network/NetworkManager.uts'
import { Data, HTTPURLResponse, NSError, NSNumber, ComparisonResult, RunLoop, Thread } from 'Foundation';
4
import { StatusCode } from './network/StatusCode.uts';
DCloud-yyl's avatar
DCloud-yyl 已提交
5
import { RequestFailImpl, UploadFileFailImpl, DownloadFileFailImpl, getErrcode } from '../unierror';
6

DCloud-yyl's avatar
DCloud-yyl 已提交
7 8
class SimpleNetworkListener extends NetworkRequestListener {
	private param : RequestOptions | null = null;
9 10 11
	private headers : Map<string, any> | null = null;
	private received : number = 0;
	private data : Data = new Data();
DCloud-yyl's avatar
DCloud-yyl 已提交
12
	constructor(param : RequestOptions) {
13 14 15 16 17 18 19 20 21 22 23
		this.param = param;
		super();
	}

	public override onStart() : void {
	}

	public override onHeadersReceived(statusCode : number, headers : Map<string, any>) : void {
		this.headers = headers;
	}
	public override onDataReceived(data : Data) : void {
DCloud-yyl's avatar
DCloud-yyl 已提交
24
		this.received += Number.from(data.count);
25 26 27 28
		this.data.append(data);
	}

	public override onFinished(response : HTTPURLResponse) : void {
DCloud-yyl's avatar
DCloud-yyl 已提交
29
		try {
30 31 32 33 34 35 36 37 38 39 40 41
			let headers = response.allHeaderFields as Map<string, any>;
			let kParam = this.param;
			let result = {};
			result['statusCode'] = response.statusCode;
			result['statusText'] = StatusCode.getStatus(new String(response.statusCode));
			if (headers != null) {
				result['header'] = headers;
			}
			let strData = this.readStringFromData(this.data, response.textEncodingName);


			let type = kParam?.responseType != null ? kParam?.responseType : kParam?.dataType;
DCloud-yyl's avatar
DCloud-yyl 已提交
42 43 44 45 46 47 48 49 50 51 52

			if (type == null && headers != null) {

				for (entry in headers) {
					let key = entry.key;
					if (key.caseInsensitiveCompare("Content-Type") == ComparisonResult.orderedSame) {
						type = headers[key] as string;
					}
				}
			}

53 54 55

			result['data'] = this.parseData(this.data, strData, type);

DCloud-yyl's avatar
DCloud-yyl 已提交
56 57
			let tmp : RequestSuccess = {
				data: result['data']!,
58 59
				statusCode: (new NSNumber(value = response.statusCode)),
				header: result['header'] ?? "",
DCloud-yyl's avatar
DCloud-yyl 已提交
60
				cookies: this.parseCookie(this.headers)
DCloud-yyl's avatar
DCloud-yyl 已提交
61
			};
62 63 64 65 66 67 68 69 70 71
			let success = kParam?.success;
			let complete = kParam?.complete;
			success?.(tmp);
			complete?.(tmp);
		} catch (e) {
		}
	}

	public override onFail(error : NSError) : void {
		let kParam = this.param;
DCloud-yyl's avatar
DCloud-yyl 已提交
72
		let code = (error as NSError).code;
73
		let errCode = code;
DCloud-yyl's avatar
DCloud-yyl 已提交
74
		let cause = error.localizedDescription;
DCloud-yyl's avatar
DCloud-yyl 已提交
75 76 77 78 79 80 81 82 83 84 85 86
		if (code == -1001) {
			errCode = 5;
		} else if (code == -1004) {
			errCode = 1000;
		} else if (code == -1009) {
			errCode = 600003;
		} else {
			errCode = 602001;
		}
		
		let failResult = new RequestFailImpl(getErrcode(Number.from(errCode)));
		failResult.cause = new SourceError(cause);
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

		let fail = kParam?.fail;
		let complete = kParam?.complete;
		fail?.(failResult);
		complete?.(failResult);
	}


	private readStringFromData(data : Data, type : string | null) : string | null {
		let result : string | null = null;
		let finalType = type;
		if (finalType == null || finalType!.length == 0) {
			finalType = "utf-8";
		}

		let cfEncoding = CFStringConvertIANACharSetNameToEncoding(finalType as CFString);
		if (cfEncoding != kCFStringEncodingInvalidId) {
			let stringEncoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
			let encode = new String.Encoding(rawValue = stringEncoding);
			result = new String(data = data, encoding = encode);
		}
		return result;
	}

DCloud-yyl's avatar
DCloud-yyl 已提交
111 112 113 114
	private parseData(data : Data | null, dataStr : string | null, type : string | null) : any | null {
		if (type != null && type!.contains("json")) {
			if (dataStr == null || dataStr!.length == 0) {
				return {};
115
			}
DCloud-yyl's avatar
DCloud-yyl 已提交
116 117
			return this.parseJson(dataStr!);
		} else if (type == 'jsonp') {
118
			if (dataStr == null || dataStr!.length == 0) {
DCloud-yyl's avatar
DCloud-yyl 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132
				return {};
			}
			let start = dataStr!.indexOf('(');
			let end = dataStr!.indexOf(')');
			if (start == 0 || start >= end) {
				return {};
			}
			start += 1;
			let tmp = dataStr!.slice(start, end);
			return this.parseJson(tmp);
		} else {
			//dataStr如果解码失败是空的时候,还需要继续尝试解码。极端情况,服务器不是utf8的,所以字符解码会出现乱码,所以特殊处理一下非utf8的字符。
			if (data == null) {
				return data;
133
			}
DCloud-yyl's avatar
DCloud-yyl 已提交
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148

			let currentStr : string | null = dataStr;
			//todo 等uts支持swift文件混编的时候,再进行处理。
			// if (currentStr == null) {
			// 	let data = cleanUTF8(data);
			// 	if (data != null) {
			// 		currentStr = new String(data = data, encoding = String.Encoding.utf8);
			// 	}
			// }

			if (currentStr == null) {
				currentStr = new String(data = data!, encoding = String.Encoding.ascii);
			}

			return currentStr;
DCloud-yyl's avatar
DCloud-yyl 已提交
149 150 151
		}
	}

DCloud-yyl's avatar
DCloud-yyl 已提交
152 153 154 155 156

	private parseJson(str : string) : any | null {
		return JSON.parse(str);
	}

DCloud-yyl's avatar
DCloud-yyl 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
	private parseCookie(header : Map<string, any> | null) : string[] {
		if (header == null) {
			return []
		}
		let cookiesStr = header!.get('Set-Cookie') as string | null
		if (cookiesStr == null) {
			cookiesStr = header!.get('set-cookie') as string | null
		}
		if (cookiesStr == null) {
			return []
		}
		let cookiesArr = new Array<string>()
		if (cookiesStr!.charAt(0) == "[" && cookiesStr!.charAt(cookiesStr!.length - 1) == "]") {
			cookiesStr = cookiesStr!.slice(1, -1)
		}

		const handleCookiesArr = cookiesStr!.split(';')
		for (let i = 0; i < handleCookiesArr.length; i++) {
			if (handleCookiesArr[i].indexOf('Expires=') != -1 || handleCookiesArr[i].indexOf('expires=') != -1) {
				cookiesArr.push(handleCookiesArr[i].replace(',', ''))
			} else {
				cookiesArr.push(handleCookiesArr[i])
179
			}
DCloud-yyl's avatar
DCloud-yyl 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
		}
		cookiesArr = cookiesArr.join(';').split(',')

		return cookiesArr
	}
}

class UploadNetworkListener implements NetworkUploadFileListener {
	private param : UploadFileOptions | null = null;
	public progressListeners : Array<UploadFileProgressUpdateCallback> = [];
	private data : Data = new Data();

	constructor(param : UploadFileOptions) {
		this.param = param;
		super();
	}

	onProgress(progressUpdate : OnProgressUpdateResult) {
		if (this.progressListeners.length != 0) {
			for (let i = 0; i < this.progressListeners.length; i++) {
				let listener = this.progressListeners[i];
				listener(progressUpdate)
202
			}
DCloud-yyl's avatar
DCloud-yyl 已提交
203 204 205 206 207 208
		}
	}

	onDataReceived(data : Data) : void {
		this.data.append(data);
	}
209

DCloud-yyl's avatar
DCloud-yyl 已提交
210 211 212 213 214 215 216 217 218 219
	onFinished(response : HTTPURLResponse) : void {
		try {
			let kParam = this.param;
			let strData = this.readStringFromData(this.data, response.textEncodingName);
			if (strData == null) {
				strData = new String(data = this.data, encoding = String.Encoding.utf8);
				// utf8 如果失败了,就用ascii,几率很小。
				if (strData == null) {
					strData = new String(data = this.data, encoding = String.Encoding.ascii);
				}
220 221
			}

DCloud-yyl's avatar
DCloud-yyl 已提交
222 223 224 225 226 227 228 229 230
			let successResult : UploadFileSuccess = {
				data: strData ?? "",
				statusCode: response.statusCode
			}
			let success = kParam?.success;
			let complete = kParam?.complete;
			success?.(successResult);
			complete?.(successResult);
		} catch (e) {
231
		}
DCloud-yyl's avatar
DCloud-yyl 已提交
232
		this.progressListeners.splice(0, this.progressListeners.length)
233 234
	}

DCloud-yyl's avatar
DCloud-yyl 已提交
235 236 237 238 239 240 241 242 243 244 245 246 247 248
	onFail(error : NSError) : void {
		let kParam = this.param;
		let code = (error as NSError).code;
		let errCode = code;
		let cause = error.localizedDescription;
		if (code == -1001) {
			errCode = 5;
		} else if (code == -1004) {
			errCode = 1000;
		} else if (code == -1009) {
			errCode = 600003;
		} else {
			errCode = 602001;
		}
249

DCloud-yyl's avatar
DCloud-yyl 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
		let failResult = new UploadFileFailImpl(getErrcode(Number.from(errCode)));
		failResult.cause = new SourceError(cause);
		let fail = kParam?.fail;
		let complete = kParam?.complete;
		fail?.(failResult);
		complete?.(failResult);
		this.progressListeners.splice(0, this.progressListeners.length)
	}


	private readStringFromData(data : Data, type : string | null) : string | null {
		let result : string | null = null;
		let finalType = type;
		if (finalType == null || finalType!.length == 0) {
			finalType = "utf-8";
		}

		let cfEncoding = CFStringConvertIANACharSetNameToEncoding(finalType as CFString);
		if (cfEncoding != kCFStringEncodingInvalidId) {
			let stringEncoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
			let encode = new String.Encoding(rawValue = stringEncoding);
			result = new String(data = data, encoding = encode);
		}
		return result;
274 275 276
	}
}

DCloud-yyl's avatar
DCloud-yyl 已提交
277
class DownloadNetworkListener implements NetworkDownloadFileListener {
DCloud-yyl's avatar
DCloud-yyl 已提交
278
	public options : DownloadFileOptions | null = null;
DCloud-yyl's avatar
DCloud-yyl 已提交
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
	public progressListeners : Array<DownloadFileProgressUpdateCallback> = [];
	private data : Data = new Data();

	constructor(options : DownloadFileOptions) {
		this.options = options;
		super();
	}

	onProgress(progressUpdate : OnProgressDownloadResult) {
		if (this.progressListeners.length != 0) {
			for (let i = 0; i < this.progressListeners.length; i++) {
				let listener = this.progressListeners[i];
				listener(progressUpdate)
			}
		}
	}

DCloud-yyl's avatar
DCloud-yyl 已提交
296 297 298 299 300 301 302 303 304 305 306 307 308
	onFinished(response : HTTPURLResponse, filePath: string) : void {
		try {
			let kParam = this.options;
			let tmp : DownloadFileSuccess = {
				tempFilePath:filePath,
				statusCode: response.statusCode
			};
			let success = kParam?.success;
			let complete = kParam?.complete;
			success?.(tmp);
			complete?.(tmp);
		} catch (e) {
		}
DCloud-yyl's avatar
DCloud-yyl 已提交
309 310 311 312 313 314 315
		this.progressListeners.splice(0, this.progressListeners.length)
	}

	onFail(error : NSError) : void {
		let kParam = this.options;
		let code = (error as NSError).code;
		let errCode = code;
DCloud-yyl's avatar
DCloud-yyl 已提交
316
		let cause = error.localizedDescription;
DCloud-yyl's avatar
DCloud-yyl 已提交
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
		if (code == -1001) {
			errCode = 5;
		} else if (code == -1004) {
			errCode = 1000;
		} else if (code == -1009) {
			errCode = 600003;
		} else {
			errCode = 602001;
		}

		let failResult = new DownloadFileFailImpl(getErrcode(Number.from(errCode)));
		failResult.cause = new SourceError(cause);
		let fail = kParam?.fail;
		let complete = kParam?.complete;
		fail?.(failResult);
		complete?.(failResult);
		this.progressListeners.splice(0, this.progressListeners.length)
	}
}


DCloud-yyl's avatar
DCloud-yyl 已提交
338 339
export const request : Request = (options : RequestOptions) : RequestTask => {
	return NetworkManager.getInstance().request(options, new SimpleNetworkListener(options));
DCloud-yyl's avatar
DCloud-yyl 已提交
340 341 342 343 344
}

export const uploadFile : UploadFile = (options : UploadFileOptions) : UploadTask => {
	return NetworkManager.getInstance().uploadFile(options, new UploadNetworkListener(options));
}
345

DCloud-yyl's avatar
DCloud-yyl 已提交
346 347
export const downloadFile : DownloadFile = (options : DownloadFileOptions) : DownloadTask => {
	return NetworkManager.getInstance().downloadFile(options, new DownloadNetworkListener(options));
348
}