UNPKG

@microsoft/microsoft-graph-client

Version:
336 lines 15.1 kB
"use strict"; /** * ------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. * See License in the project root for license information. * ------------------------------------------------------------------------------------------- */ Object.defineProperty(exports, "__esModule", { value: true }); exports.LargeFileUploadTask = void 0; var tslib_1 = require("tslib"); /** * @module LargeFileUploadTask */ var GraphClientError_1 = require("../GraphClientError"); var GraphResponseHandler_1 = require("../GraphResponseHandler"); var ResponseType_1 = require("../ResponseType"); var Range_1 = require("./FileUploadTask/Range"); var UploadResult_1 = require("./FileUploadTask/UploadResult"); /** * @class * Class representing LargeFileUploadTask */ var LargeFileUploadTask = /** @class */ (function () { /** * @public * @constructor * Constructs a LargeFileUploadTask * @param {Client} client - The GraphClient instance * @param {FileObject} file - The FileObject holding details of a file that needs to be uploaded * @param {LargeFileUploadSession} uploadSession - The upload session to which the upload has to be done * @param {LargeFileUploadTaskOptions} options - The upload task options * @returns An instance of LargeFileUploadTask */ function LargeFileUploadTask(client, file, uploadSession, options) { if (options === void 0) { options = {}; } /** * @private * Default value for the rangeSize */ this.DEFAULT_FILE_SIZE = 5 * 1024 * 1024; this.client = client; if (!file.sliceFile) { throw new GraphClientError_1.GraphClientError("Please pass the FileUpload object, StreamUpload object or any custom implementation of the FileObject interface"); } else { this.file = file; } this.file = file; if (!options.rangeSize) { options.rangeSize = this.DEFAULT_FILE_SIZE; } this.options = options; this.uploadSession = uploadSession; this.nextRange = new Range_1.Range(0, this.options.rangeSize - 1); } /** * @public * @static * @async * Makes request to the server to create an upload session * @param {Client} client - The GraphClient instance * @param {string} requestUrl - The URL to create the upload session * @param {any} payload - The payload that needs to be sent * @param {KeyValuePairObjectStringNumber} headers - The headers that needs to be sent * @returns The promise that resolves to LargeFileUploadSession */ LargeFileUploadTask.createUploadSession = function (client, requestUrl, payload, headers) { if (headers === void 0) { headers = {}; } return tslib_1.__awaiter(this, void 0, void 0, function () { var session, largeFileUploadSession; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, client .api(requestUrl) .headers(headers) .post(payload)]; case 1: session = _a.sent(); largeFileUploadSession = { url: session.uploadUrl, expiry: new Date(session.expirationDateTime), isCancelled: false, }; return [2 /*return*/, largeFileUploadSession]; } }); }); }; /** * @private * Parses given range string to the Range instance * @param {string[]} ranges - The ranges value * @returns The range instance */ LargeFileUploadTask.prototype.parseRange = function (ranges) { var rangeStr = ranges[0]; if (typeof rangeStr === "undefined" || rangeStr === "") { return new Range_1.Range(); } var firstRange = rangeStr.split("-"); var minVal = parseInt(firstRange[0], 10); var maxVal = parseInt(firstRange[1], 10); if (Number.isNaN(maxVal)) { maxVal = this.file.size - 1; } return new Range_1.Range(minVal, maxVal); }; /** * @private * Updates the expiration date and the next range * @param {UploadStatusResponse} response - The response of the upload status * @returns Nothing */ LargeFileUploadTask.prototype.updateTaskStatus = function (response) { this.uploadSession.expiry = new Date(response.expirationDateTime); this.nextRange = this.parseRange(response.nextExpectedRanges); }; /** * @public * Gets next range that needs to be uploaded * @returns The range instance */ LargeFileUploadTask.prototype.getNextRange = function () { if (this.nextRange.minValue === -1) { return this.nextRange; } var minVal = this.nextRange.minValue; var maxValue = minVal + this.options.rangeSize - 1; if (maxValue >= this.file.size) { maxValue = this.file.size - 1; } return new Range_1.Range(minVal, maxValue); }; /** * @deprecated This function has been moved into FileObject interface. * @public * Slices the file content to the given range * @param {Range} range - The range value * @returns The sliced ArrayBuffer or Blob */ LargeFileUploadTask.prototype.sliceFile = function (range) { console.warn("The LargeFileUploadTask.sliceFile() function has been deprecated and moved into the FileObject interface."); if (this.file.content instanceof ArrayBuffer || this.file.content instanceof Blob || this.file.content instanceof Uint8Array) { return this.file.content.slice(range.minValue, range.maxValue + 1); } throw new GraphClientError_1.GraphClientError("The LargeFileUploadTask.sliceFile() function expects only Blob, ArrayBuffer or Uint8Array file content. Please note that the sliceFile() function is deprecated."); }; /** * @public * @async * Uploads file to the server in a sequential order by slicing the file * @returns The promise resolves to uploaded response */ LargeFileUploadTask.prototype.upload = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var uploadEventHandlers, nextRange, err, fileSlice, rawResponse, responseBody, res; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: uploadEventHandlers = this.options && this.options.uploadEventHandlers; _a.label = 1; case 1: if (!!this.uploadSession.isCancelled) return [3 /*break*/, 5]; nextRange = this.getNextRange(); if (nextRange.maxValue === -1) { err = new Error("Task with which you are trying to upload is already completed, Please check for your uploaded file"); err.name = "Invalid Session"; throw err; } return [4 /*yield*/, this.file.sliceFile(nextRange)]; case 2: fileSlice = _a.sent(); return [4 /*yield*/, this.uploadSliceGetRawResponse(fileSlice, nextRange, this.file.size)]; case 3: rawResponse = _a.sent(); if (!rawResponse) { throw new GraphClientError_1.GraphClientError("Something went wrong! Large file upload slice response is null."); } return [4 /*yield*/, GraphResponseHandler_1.GraphResponseHandler.getResponse(rawResponse)]; case 4: responseBody = _a.sent(); /** * (rawResponse.status === 201) -> This condition is applicable for OneDrive, PrintDocument and Outlook APIs. * (rawResponse.status === 200 && responseBody.id) -> This additional condition is applicable only for OneDrive API. */ if (rawResponse.status === 201 || (rawResponse.status === 200 && responseBody.id)) { this.reportProgress(uploadEventHandlers, nextRange); return [2 /*return*/, UploadResult_1.UploadResult.CreateUploadResult(responseBody, rawResponse.headers)]; } res = { expirationDateTime: responseBody.expirationDateTime || responseBody.ExpirationDateTime, nextExpectedRanges: responseBody.NextExpectedRanges || responseBody.nextExpectedRanges, }; this.updateTaskStatus(res); this.reportProgress(uploadEventHandlers, nextRange); return [3 /*break*/, 1]; case 5: return [2 /*return*/]; } }); }); }; LargeFileUploadTask.prototype.reportProgress = function (uploadEventHandlers, nextRange) { if (uploadEventHandlers && uploadEventHandlers.progress) { uploadEventHandlers.progress(nextRange, uploadEventHandlers.extraCallbackParam); } }; /** * @public * @async * Uploads given slice to the server * @param {ArrayBuffer | Blob | File} fileSlice - The file slice * @param {Range} range - The range value * @param {number} totalSize - The total size of a complete file * @returns The response body of the upload slice result */ LargeFileUploadTask.prototype.uploadSlice = function (fileSlice, range, totalSize) { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.client .api(this.uploadSession.url) .headers({ "Content-Length": "".concat(range.maxValue - range.minValue + 1), "Content-Range": "bytes ".concat(range.minValue, "-").concat(range.maxValue, "/").concat(totalSize), "Content-Type": "application/octet-stream", }) .put(fileSlice)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; /** * @public * @async * Uploads given slice to the server * @param {unknown} fileSlice - The file slice * @param {Range} range - The range value * @param {number} totalSize - The total size of a complete file * @returns The raw response of the upload slice result */ LargeFileUploadTask.prototype.uploadSliceGetRawResponse = function (fileSlice, range, totalSize) { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.client .api(this.uploadSession.url) .headers({ "Content-Length": "".concat(range.maxValue - range.minValue + 1), "Content-Range": "bytes ".concat(range.minValue, "-").concat(range.maxValue, "/").concat(totalSize), "Content-Type": "application/octet-stream", }) .responseType(ResponseType_1.ResponseType.RAW) .put(fileSlice)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; /** * @public * @async * Deletes upload session in the server * @returns The promise resolves to cancelled response */ LargeFileUploadTask.prototype.cancel = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var cancelResponse; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.client .api(this.uploadSession.url) .responseType(ResponseType_1.ResponseType.RAW) .delete()]; case 1: cancelResponse = _a.sent(); if (cancelResponse.status === 204) { this.uploadSession.isCancelled = true; } return [2 /*return*/, cancelResponse]; } }); }); }; /** * @public * @async * Gets status for the upload session * @returns The promise resolves to the status enquiry response */ LargeFileUploadTask.prototype.getStatus = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var response; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.client.api(this.uploadSession.url).get()]; case 1: response = _a.sent(); this.updateTaskStatus(response); return [2 /*return*/, response]; } }); }); }; /** * @public * @async * Resumes upload session and continue uploading the file from the last sent range * @returns The promise resolves to the uploaded response */ LargeFileUploadTask.prototype.resume = function () { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.getStatus()]; case 1: _a.sent(); return [4 /*yield*/, this.upload()]; case 2: return [2 /*return*/, _a.sent()]; } }); }); }; /** * @public * @async * Get the upload session information * @returns The large file upload session */ LargeFileUploadTask.prototype.getUploadSession = function () { return this.uploadSession; }; return LargeFileUploadTask; }()); exports.LargeFileUploadTask = LargeFileUploadTask; //# sourceMappingURL=LargeFileUploadTask.js.map