@nos-sdk/nos-node-sdk
Version:
NOS Node.js SDK实现了NOS对象操作接口,基于此SDK能方便快速地实现JavaScript应用程序来使用NOS的对象存储服务。
234 lines • 10.8 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const date_fns_1 = require("date-fns");
const fs = __importStar(require("fs"));
const ramda_1 = require("ramda");
const util = __importStar(require("util"));
const client_1 = require("../client");
const constant_1 = require("../lib/constant");
const util_1 = require("../lib/util");
class NosClientMultipartUploadExt extends client_1.NosBaseClient {
initMultipartUpload(params) {
return __awaiter(this, void 0, void 0, function* () {
const { bucket, headers, resource } = this.validateParams(params);
Object.assign(resource, {
uploads: true,
});
const result = yield this.requestBody('post', headers, resource);
return result.initiateMultipartUploadResult.uploadId;
});
}
abortMultipartUpload(params) {
return __awaiter(this, void 0, void 0, function* () {
const { bucket, headers, resource } = this.validateParams(params);
Object.assign(resource, {
uploadId: params.uploadId,
});
const result = yield this.requestBody('delete', headers, resource);
return true;
});
}
uploadMultipart(params) {
return __awaiter(this, void 0, void 0, function* () {
const { bucket, headers, resource } = this.validateParams(params);
Object.assign(resource, {
partNumber: params.partNumber,
uploadId: params.uploadId,
});
const resp = yield this.request('put', headers, resource, params.body);
let eTag = resp.headers.get('etag');
if (eTag.charAt(0) === '\"' && eTag.charAt(eTag.length - 1) === '\"') {
eTag = eTag.slice(1, -1);
}
return {
partNumber: params.partNumber,
eTag: eTag,
size: params.body.length,
lastModified: date_fns_1.parse(resp.headers.get('date')),
};
});
}
listParts(params) {
return __awaiter(this, void 0, void 0, function* () {
const { bucket, headers, resource } = this.validateParams(params);
Object.assign(resource, util_1.compactObject({
uploadId: params.uploadId,
'max-parts': params.limit,
'part-number-marker': params.marker,
}));
const { listPartsResult: result } = yield this.requestBody('get', headers, resource);
let parts = result.part;
if (ramda_1.type(parts) !== 'Array') {
parts = [parts];
}
for (const part of parts) {
part.lastModified = date_fns_1.parse(part.lastModified);
}
return Object.assign({}, ramda_1.pick(['isTruncated', 'owner', 'storageClass', 'bucket'], result), { limit: result.maxParts, nextMarker: result.nextPartNumberMarker, items: parts });
});
}
listMultipartUpload(params = {}) {
return __awaiter(this, void 0, void 0, function* () {
const { bucket, headers, resource } = this.validateParams(params);
Object.assign(resource, util_1.compactObject({
uploads: true,
prefix: params.prefix,
'key-marker': params.marker,
'max-uploads': params.limit,
}));
if (params.limit) {
headers['max-uploads'] = params.limit;
}
const { listMultipartUploadsResult: result } = yield this.requestBody('get', headers, resource);
let uploads = util_1.normalizeArray(result.upload);
if (ramda_1.type(uploads) !== 'Array') {
uploads = [uploads];
}
for (const upload of uploads) {
upload.initiated = date_fns_1.parse(upload.initiated);
}
return Object.assign({}, ramda_1.pick(['isTruncated'], result), { items: uploads, nextMarker: result.nextKeyMarker, bucket: result.bucket, limit: params.limit || 1000 });
});
}
completeMultipartUpload(params) {
return __awaiter(this, void 0, void 0, function* () {
const { bucket, headers, resource } = this.validateParams(params);
Object.assign(resource, {
uploadId: params.uploadId,
});
const result = yield this.requestBody('post', headers, resource, {
completeMultipartUpload: {
part: params.parts.map(part => ({ partNumber: part.partNumber, eTag: part.eTag })),
},
});
return result.completeMultipartUploadResult;
});
}
putBigObject(params) {
return __awaiter(this, void 0, void 0, function* () {
const uploadId = yield this.initMultipartUpload(params);
const stream = 'body' in params ? params.body : fs.createReadStream(params.file);
const lengthComputable = 'file' in params;
const { parallel = Infinity, maxPart = constant_1.MAX_PART_LENGTH } = params;
let totalLength = 0;
if ('file' in params) {
const stat = yield util.promisify(fs.stat)(params.file);
totalLength = stat.size;
}
const rootParams = {
uploadId,
objectKey: params.objectKey,
bucket: params.bucket,
};
const bufs = [];
const partPromises = [];
let length = 0;
let partNumber = 1;
let aborted = false;
let uploadedLength = 0;
let onProgress = params.onProgress;
let workers = 0;
const uploadPart = () => __awaiter(this, void 0, void 0, function* () {
const tBuf = Buffer.concat(bufs);
const tPartNumber = partNumber++;
bufs.length = 0;
length = 0;
if (++workers >= parallel) {
stream.pause();
}
const part = yield this.uploadMultipart(Object.assign({}, rootParams, { partNumber: tPartNumber, body: tBuf }));
workers--;
if (stream.isPaused()) {
stream.resume();
}
uploadedLength += tBuf.length;
if (onProgress) {
onProgress({
lengthComputable,
uploaded: uploadedLength,
total: totalLength,
});
}
return part;
});
return yield new Promise((resolve, reject) => {
const completeUpload = () => __awaiter(this, void 0, void 0, function* () {
const parts = yield Promise.all(partPromises);
const resp = yield this.completeMultipartUpload(Object.assign({}, rootParams, { parts }));
resolve(resp);
});
const abortUpload = (e) => {
if (aborted) {
return;
}
stream.removeListener('data', onData);
aborted = true;
reject(e);
};
const onData = (data) => {
if (data.length + length > maxPart) {
const partPromise = uploadPart();
partPromise.catch(abortUpload);
partPromises.push(partPromise);
}
bufs.push(data);
length += data.length;
};
stream.on('data', onData);
stream.once('end', () => {
if (length) {
const partPromise = uploadPart();
partPromise.catch(abortUpload);
partPromises.push(partPromise);
}
completeUpload().catch(abortUpload);
});
stream.once('error', abortUpload);
});
});
}
}
__decorate([
util_1.Callbackable
], NosClientMultipartUploadExt.prototype, "initMultipartUpload", null);
__decorate([
util_1.Callbackable
], NosClientMultipartUploadExt.prototype, "abortMultipartUpload", null);
__decorate([
util_1.Callbackable
], NosClientMultipartUploadExt.prototype, "uploadMultipart", null);
__decorate([
util_1.Callbackable
], NosClientMultipartUploadExt.prototype, "listParts", null);
__decorate([
util_1.Callbackable
], NosClientMultipartUploadExt.prototype, "listMultipartUpload", null);
__decorate([
util_1.Callbackable
], NosClientMultipartUploadExt.prototype, "completeMultipartUpload", null);
__decorate([
util_1.Callbackable
], NosClientMultipartUploadExt.prototype, "putBigObject", null);
exports.NosClientMultipartUploadExt = NosClientMultipartUploadExt;
//# sourceMappingURL=multipart-upload.js.map