Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add onXHRProgress option #1107

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 47 additions & 27 deletions lib/browser/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function Client(options, ctx) {
this.options = Client.initOptions(options);
}

this.options.cancelFlag = false;// cancel flag: if true need to be cancelled, default false
this.options.cancelFlag = false; // cancel flag: if true need to be cancelled, default false

// support custom agent and urllib client
if (this.options.urllib) {
Expand All @@ -68,18 +68,22 @@ module.exports = Client;

Client.initOptions = function initOptions(options) {
if (!options.stsToken) {
console.warn('Please use STS Token for safety, see more details at https://help.aliyun.com/document_detail/32077.html');
console.warn(
'Please use STS Token for safety, see more details at https://help.aliyun.com/document_detail/32077.html'
);
}
const opts = Object.assign({
secure: isHttpsWebProtocol(),
// for browser compatibility disable fetch.
useFetch: false,
}, options);
const opts = Object.assign(
{
secure: isHttpsWebProtocol(),
// for browser compatibility disable fetch.
useFetch: false
},
options
);

return _initOptions(opts);
};


/**
* prototype
*/
Expand Down Expand Up @@ -179,7 +183,12 @@ proto.authorization = function authorization(method, resource, subres, headers)
parameters: subres
});

return signUtils.authorization(this.options.accessKeyId, this.options.accessKeySecret, stringToSign, this.options.headerEncoding);
return signUtils.authorization(
this.options.accessKeyId,
this.options.accessKeySecret,
stringToSign,
this.options.headerEncoding
);
};

/**
Expand All @@ -204,8 +213,8 @@ proto.authorization = function authorization(method, resource, subres, headers)
proto.request = async function (params) {
if (this.options.retryMax) {
return await retry(request.bind(this), this.options.retryMax, {
errorHandler: (err) => {
const _errHandle = (_err) => {
errorHandler: err => {
const _errHandle = _err => {
if (params.stream) return false;
const statusErr = [-1, -2].includes(_err.status);
const requestErrorRetryHandle = this.options.requestErrorRetryHandle || (() => true);
Expand Down Expand Up @@ -233,7 +242,14 @@ async function request(params) {
const useStream = !!params.stream;
try {
result = await this.urllib.request(reqParams.url, reqParams.params);
this.debug('response %s %s, got %s, headers: %j', params.method, reqParams.url, result.status, result.headers, 'info');
this.debug(
'response %s %s, got %s, headers: %j',
params.method,
reqParams.url,
result.status,
result.headers,
'info'
);
} catch (err) {
reqErr = err;
}
Expand Down Expand Up @@ -282,7 +298,7 @@ proto._escape = function _escape(name) {
*/

proto._getUserAgent = function _getUserAgent() {
const agent = (process && process.browser) ? 'js' : 'nodejs';
const agent = process && process.browser ? 'js' : 'nodejs';
const sdk = `aliyun-sdk-${agent}/${pkg.version}`;
let plat = platform.description;
if (!plat && process) {
Expand All @@ -306,7 +322,7 @@ proto._checkUserAgent = function _checkUserAgent(ua) {
*/

proto.checkBrowserAndVersion = function checkBrowserAndVersion(name, version) {
return ((bowser.name === name) && (bowser.version.split('.')[0] === version));
return bowser.name === name && bowser.version.split('.')[0] === version;
};

/**
Expand All @@ -321,16 +337,20 @@ proto.parseXML = function parseXMLThunk(str) {
if (Buffer.isBuffer(str)) {
str = str.toString();
}
xml.parseString(str, {
explicitRoot: false,
explicitArray: false
}, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
xml.parseString(
str,
{
explicitRoot: false,
explicitArray: false
},
(err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
}
});
);
});
};

Expand All @@ -344,7 +364,8 @@ proto.parseXML = function parseXMLThunk(str) {
proto.requestError = async function requestError(result) {
let err = null;
if (!result.data || !result.data.length) {
if (result.status === -1 || result.status === -2) { // -1 is net error , -2 is timeout
if (result.status === -1 || result.status === -2) {
// -1 is net error , -2 is timeout
err = new Error(result.message);
err.name = result.name;
err.status = result.status;
Expand Down Expand Up @@ -375,7 +396,7 @@ proto.requestError = async function requestError(result) {

let info;
try {
info = await this.parseXML(message) || {};
info = (await this.parseXML(message)) || {};
} catch (error) {
this.debug(message, 'error');
error.message += `\nraw xml: ${message}`;
Expand All @@ -384,7 +405,7 @@ proto.requestError = async function requestError(result) {
return error;
}

let msg = info.Message || (`unknow request error, status: ${result.status}`);
let msg = info.Message || `unknow request error, status: ${result.status}`;
if (info.Condition) {
msg += ` (condition: ${info.Condition})`;
}
Expand All @@ -400,4 +421,3 @@ proto.requestError = async function requestError(result) {
this.debug('generate error %j', err, 'error');
return err;
};

45 changes: 32 additions & 13 deletions lib/browser/managed-upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const { isFile } = require('../common/utils/isFile');
const { isArray } = require('../common/utils/isArray');
const { isBuffer } = require('../common/utils/isBuffer');
const { retry } = require('../common/utils/retry');
const { calculatePercentage } = require('../common/utils/calculatePercentage');

const proto = exports;

Expand Down Expand Up @@ -119,6 +120,9 @@ proto._resumeMultipart = async function _resumeMultipart(checkpoint, options) {
}
const { file, fileSize, partSize, uploadId, doneParts, name } = checkpoint;

// total loaded percentage
const partDetail = {};

const internalDoneParts = [];

if (doneParts.length > 0) {
Expand All @@ -142,10 +146,24 @@ proto._resumeMultipart = async function _resumeMultipart(checkpoint, options) {
};

let result;
let onXHRProgress;
if (options.onXHRProgress) {
onXHRProgress = (p, l, t) => {
partDetail[partNo] = {
percentage: p,
loaded: l,
total: t
};
const detail = calculatePercentage(fileSize, partDetail);
options.onXHRProgress(detail.percentage, detail.loaded, detail.total);
};
}

try {
result = await self._uploadPart(name, uploadId, partNo, data, {
timeout: options.timeout,
disabledMD5: options.disabledMD5
disabledMD5: options.disabledMD5,
onXHRProgress
});
} catch (error) {
if (error.status === 404) {
Expand Down Expand Up @@ -195,18 +213,19 @@ proto._resumeMultipart = async function _resumeMultipart(checkpoint, options) {
const jobErr = await this._parallel(
todo,
parallel,
value => new Promise((resolve, reject) => {
uploadPartJob(that, value)
.then(result => {
if (result) {
internalDoneParts.push(result);
}
resolve();
})
.catch(err => {
reject(err);
});
})
value =>
new Promise((resolve, reject) => {
uploadPartJob(that, value)
.then(result => {
if (result) {
internalDoneParts.push(result);
}
resolve();
})
.catch(err => {
reject(err);
});
})
);
multipartFinish = true;

Expand Down
5 changes: 5 additions & 0 deletions lib/browser/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ proto.put = async function put(name, file, options) {
params.disabledMD5 = options.disabledMD5;
params.content = content;
params.successStatuses = [200];
if (options.onXHRProgress && typeof options.onXHRProgress === 'function') {
params.onXHRProgress = (percentage, loaded, total) => {
options.onXHRProgress(percentage, loaded, total);
};
}

const result = await this.request(params);

Expand Down
5 changes: 5 additions & 0 deletions lib/common/multipart.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@ proto._uploadPart = async function _uploadPart(name, uploadId, partNo, data, opt
isBrowserEnv ? (params.content = data.content) : (params.stream = data.stream);
params.successStatuses = [200];
params.disabledMD5 = options.disabledMD5;
if (options.onXHRProgress && typeof options.onXHRProgress === 'function') {
params.onXHRProgress = (percentage, loaded, total) => {
options.onXHRProgress(percentage, loaded, total);
};
}

const result = await this.request(params);

Expand Down
5 changes: 5 additions & 0 deletions lib/common/utils/calculatePercentage.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export declare const calculatePercentage: (fileSize: number, partList: any) => {
percentage: number;
loaded: number;
total: number;
};
11 changes: 11 additions & 0 deletions lib/common/utils/calculatePercentage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculatePercentage = void 0;
exports.calculatePercentage = (fileSize, partList) => {
const result = { percentage: 0, loaded: 0, total: fileSize };
Object.keys(partList).forEach(i => {
result.loaded += partList[i].loaded;
});
result.percentage = (result.loaded / fileSize) * 100;
return result;
};
8 changes: 8 additions & 0 deletions lib/common/utils/calculatePercentage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const calculatePercentage = (fileSize: number, partList: any) => {
const result = { percentage: 0, loaded: 0, total: fileSize };
Object.keys(partList).forEach(i => {
result.loaded += partList[i].loaded;
});
result.percentage = (result.loaded / fileSize) * 100;
return result;
};
10 changes: 4 additions & 6 deletions lib/common/utils/createRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function createRequest(params) {
date = +new Date() + this.options.amendTimeSkewed;
}
const headers = {
'x-oss-date': dateFormat(date, 'UTC:ddd, dd mmm yyyy HH:MM:ss \'GMT\''),
'x-oss-date': dateFormat(date, "UTC:ddd, dd mmm yyyy HH:MM:ss 'GMT'")
};
if (typeof window !== 'undefined') {
headers['x-oss-user-agent'] = this.userAgent;
Expand Down Expand Up @@ -52,10 +52,7 @@ function createRequest(params) {
}
if (params.content) {
if (!params.disabledMD5) {
headers['Content-MD5'] = crypto
.createHash('md5')
.update(Buffer.from(params.content, 'utf8'))
.digest('base64');
headers['Content-MD5'] = crypto.createHash('md5').update(Buffer.from(params.content, 'utf8')).digest('base64');
}
if (!headers['Content-Length']) {
headers['Content-Length'] = params.content.length;
Expand Down Expand Up @@ -86,7 +83,8 @@ function createRequest(params) {
timeout,
writeStream: params.writeStream,
customResponse: params.customResponse,
ctx: params.ctx || this.ctx
ctx: params.ctx || this.ctx,
onXHRProgress: params.onXHRProgress
};
if (this.agent) {
reqParams.agent = this.agent;
Expand Down
26 changes: 15 additions & 11 deletions lib/common/utils/createRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ const { setRegion } = require('./setRegion');
const { getReqUrl } = require('../client/getReqUrl');

interface Headers {
[propName: string]: any
'x-oss-date': string,
'x-oss-user-agent'?: string,
[propName: string]: any;
'x-oss-date': string;
'x-oss-user-agent'?: string;
}

interface ReqParams {
[propName: string]: any
[propName: string]: any;
}

function getHeader(headers: Headers, name: string) {
Expand All @@ -34,7 +34,7 @@ export function createRequest(this: any, params) {
date = +new Date() + this.options.amendTimeSkewed;
}
const headers: Headers = {
'x-oss-date': dateFormat(date, 'UTC:ddd, dd mmm yyyy HH:MM:ss \'GMT\''),
'x-oss-date': dateFormat(date, "UTC:ddd, dd mmm yyyy HH:MM:ss 'GMT'")
};

if (typeof window !== 'undefined') {
Expand Down Expand Up @@ -69,10 +69,7 @@ export function createRequest(this: any, params) {

if (params.content) {
if (!params.disabledMD5) {
headers['Content-MD5'] = crypto
.createHash('md5')
.update(Buffer.from(params.content, 'utf8'))
.digest('base64');
headers['Content-MD5'] = crypto.createHash('md5').update(Buffer.from(params.content, 'utf8')).digest('base64');
}
if (!headers['Content-Length']) {
headers['Content-Length'] = params.content.length;
Expand All @@ -87,7 +84,13 @@ export function createRequest(this: any, params) {
}

const authResource = this._getResource(params);
headers.authorization = this.authorization(params.method, authResource, params.subres, headers, this.options.headerEncoding);
headers.authorization = this.authorization(
params.method,
authResource,
params.subres,
headers,
this.options.headerEncoding
);

// const url = this._getReqUrl(params);
if (isIP(this.options.endpoint.hostname)) {
Expand All @@ -106,7 +109,8 @@ export function createRequest(this: any, params) {
timeout,
writeStream: params.writeStream,
customResponse: params.customResponse,
ctx: params.ctx || this.ctx
ctx: params.ctx || this.ctx,
onXHRProgress: params.onXHRProgress
};
if (this.agent) {
reqParams.agent = this.agent;
Expand Down
Loading