UNPKG

@microsoft/microsoft-graph-client

Version:
132 lines 7.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StreamUpload = void 0; var tslib_1 = require("tslib"); var GraphClientError_1 = require("../../../GraphClientError"); /** * @class * FileObject class for Readable Stream upload */ var StreamUpload = /** @class */ (function () { function StreamUpload(content, name, size) { this.content = content; this.name = name; this.size = size; if (!content || !name || !size) { throw new GraphClientError_1.GraphClientError("Please provide the Readable Stream content, name of the file and size of the file"); } } /** * @public * Slices the file content to the given range * @param {Range} range - The range value * @returns The sliced file part */ StreamUpload.prototype.sliceFile = function (range) { return tslib_1.__awaiter(this, void 0, void 0, function () { var rangeSize, bufs, previousRangeMin, previousRangeMax, _a, _b, slicedChunk; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: rangeSize = range.maxValue - range.minValue + 1; bufs = []; /** * The sliceFile reads the first `rangeSize` number of bytes from the stream. * The previousSlice property is used to seek the range of bytes in the previous slice. * Suppose, the sliceFile reads bytes from `10 - 20` from the stream but the upload of this slice fails. * When the user resumes, the stream will have bytes from position 21. * The previousSlice.Range is used to compare if the requested range is cached in the previousSlice property or present in the Readable Stream. */ if (this.previousSlice) { if (range.minValue < this.previousSlice.range.minValue) { throw new GraphClientError_1.GraphClientError("An error occurred while uploading the stream. Please restart the stream upload from the first byte of the file."); } if (range.minValue < this.previousSlice.range.maxValue) { previousRangeMin = this.previousSlice.range.minValue; previousRangeMax = this.previousSlice.range.maxValue; // Check if the requested range is same as previously sliced range if (range.minValue === previousRangeMin && range.maxValue === previousRangeMax) { return [2 /*return*/, this.previousSlice.fileSlice]; } /** * The following check considers a possibility * of an upload failing after some of the bytes of the previous slice * were successfully uploaded. * Example - Previous slice range - `10 - 20`. Current requested range is `15 - 20`. */ if (range.maxValue === previousRangeMax) { return [2 /*return*/, this.previousSlice.fileSlice.slice(range.minValue, range.maxValue + 1)]; } /** * If an upload fails after some of the bytes of the previous slice * were successfully uploaded and the new Range.Maximum is greater than the previous Range.Maximum * Example - Previous slice range - `10 - 20`. Current requested range is `15 - 25`, * then read the bytes from position 15 to 20 from previousSlice.fileSlice and read bytes from position 21 to 25 from the Readable Stream */ bufs.push(this.previousSlice.fileSlice.slice(range.minValue, previousRangeMax + 1)); rangeSize = range.maxValue - previousRangeMax; } } if (!(this.content && this.content.readable)) return [3 /*break*/, 4]; if (!(this.content.readableLength >= rangeSize)) return [3 /*break*/, 1]; bufs.push(this.content.read(rangeSize)); return [3 /*break*/, 3]; case 1: _b = (_a = bufs).push; return [4 /*yield*/, this.readNBytesFromStream(rangeSize)]; case 2: _b.apply(_a, [_c.sent()]); _c.label = 3; case 3: return [3 /*break*/, 5]; case 4: throw new GraphClientError_1.GraphClientError("Stream is not readable."); case 5: slicedChunk = Buffer.concat(bufs); this.previousSlice = { fileSlice: slicedChunk, range: range }; return [2 /*return*/, slicedChunk]; } }); }); }; /** * @private * Reads the specified byte size from the stream * @param {number} size - The size of bytes to be read * @returns Buffer with the given length of data. */ StreamUpload.prototype.readNBytesFromStream = function (size) { var _this = this; return new Promise(function (resolve, reject) { var chunks = []; var remainder = size; var length = 0; _this.content.on("end", function () { if (remainder > 0) { return reject(new GraphClientError_1.GraphClientError("Stream ended before reading required range size")); } }); _this.content.on("readable", function () { /** * (chunk = this.content.read(size)) can return null if size of stream is less than 'size' parameter. * Read the remainder number of bytes from the stream iteratively as they are available. */ var chunk; while (length < size && (chunk = _this.content.read(remainder)) !== null) { length += chunk.length; chunks.push(chunk); if (remainder > 0) { remainder = size - length; } } if (length === size) { return resolve(Buffer.concat(chunks)); } if (!_this.content || !_this.content.readable) { return reject(new GraphClientError_1.GraphClientError("Error encountered while reading the stream during the upload")); } }); }); }; return StreamUpload; }()); exports.StreamUpload = StreamUpload; //# sourceMappingURL=StreamUpload.js.map