UNPKG

15.1 kBJavaScriptView Raw
1"use strict";
2/**
3 * -------------------------------------------------------------------------------------------
4 * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
5 * See License in the project root for license information.
6 * -------------------------------------------------------------------------------------------
7 */
8Object.defineProperty(exports, "__esModule", { value: true });
9exports.LargeFileUploadTask = void 0;
10var tslib_1 = require("tslib");
11/**
12 * @module LargeFileUploadTask
13 */
14var GraphClientError_1 = require("../GraphClientError");
15var GraphResponseHandler_1 = require("../GraphResponseHandler");
16var ResponseType_1 = require("../ResponseType");
17var Range_1 = require("./FileUploadTask/Range");
18var UploadResult_1 = require("./FileUploadTask/UploadResult");
19/**
20 * @class
21 * Class representing LargeFileUploadTask
22 */
23var LargeFileUploadTask = /** @class */ (function () {
24 /**
25 * @public
26 * @constructor
27 * Constructs a LargeFileUploadTask
28 * @param {Client} client - The GraphClient instance
29 * @param {FileObject} file - The FileObject holding details of a file that needs to be uploaded
30 * @param {LargeFileUploadSession} uploadSession - The upload session to which the upload has to be done
31 * @param {LargeFileUploadTaskOptions} options - The upload task options
32 * @returns An instance of LargeFileUploadTask
33 */
34 function LargeFileUploadTask(client, file, uploadSession, options) {
35 if (options === void 0) { options = {}; }
36 /**
37 * @private
38 * Default value for the rangeSize
39 */
40 this.DEFAULT_FILE_SIZE = 5 * 1024 * 1024;
41 this.client = client;
42 if (!file.sliceFile) {
43 throw new GraphClientError_1.GraphClientError("Please pass the FileUpload object, StreamUpload object or any custom implementation of the FileObject interface");
44 }
45 else {
46 this.file = file;
47 }
48 this.file = file;
49 if (!options.rangeSize) {
50 options.rangeSize = this.DEFAULT_FILE_SIZE;
51 }
52 this.options = options;
53 this.uploadSession = uploadSession;
54 this.nextRange = new Range_1.Range(0, this.options.rangeSize - 1);
55 }
56 /**
57 * @public
58 * @static
59 * @async
60 * Makes request to the server to create an upload session
61 * @param {Client} client - The GraphClient instance
62 * @param {string} requestUrl - The URL to create the upload session
63 * @param {any} payload - The payload that needs to be sent
64 * @param {KeyValuePairObjectStringNumber} headers - The headers that needs to be sent
65 * @returns The promise that resolves to LargeFileUploadSession
66 */
67 LargeFileUploadTask.createUploadSession = function (client, requestUrl, payload, headers) {
68 if (headers === void 0) { headers = {}; }
69 return tslib_1.__awaiter(this, void 0, void 0, function () {
70 var session, largeFileUploadSession;
71 return tslib_1.__generator(this, function (_a) {
72 switch (_a.label) {
73 case 0: return [4 /*yield*/, client
74 .api(requestUrl)
75 .headers(headers)
76 .post(payload)];
77 case 1:
78 session = _a.sent();
79 largeFileUploadSession = {
80 url: session.uploadUrl,
81 expiry: new Date(session.expirationDateTime),
82 isCancelled: false,
83 };
84 return [2 /*return*/, largeFileUploadSession];
85 }
86 });
87 });
88 };
89 /**
90 * @private
91 * Parses given range string to the Range instance
92 * @param {string[]} ranges - The ranges value
93 * @returns The range instance
94 */
95 LargeFileUploadTask.prototype.parseRange = function (ranges) {
96 var rangeStr = ranges[0];
97 if (typeof rangeStr === "undefined" || rangeStr === "") {
98 return new Range_1.Range();
99 }
100 var firstRange = rangeStr.split("-");
101 var minVal = parseInt(firstRange[0], 10);
102 var maxVal = parseInt(firstRange[1], 10);
103 if (Number.isNaN(maxVal)) {
104 maxVal = this.file.size - 1;
105 }
106 return new Range_1.Range(minVal, maxVal);
107 };
108 /**
109 * @private
110 * Updates the expiration date and the next range
111 * @param {UploadStatusResponse} response - The response of the upload status
112 * @returns Nothing
113 */
114 LargeFileUploadTask.prototype.updateTaskStatus = function (response) {
115 this.uploadSession.expiry = new Date(response.expirationDateTime);
116 this.nextRange = this.parseRange(response.nextExpectedRanges);
117 };
118 /**
119 * @public
120 * Gets next range that needs to be uploaded
121 * @returns The range instance
122 */
123 LargeFileUploadTask.prototype.getNextRange = function () {
124 if (this.nextRange.minValue === -1) {
125 return this.nextRange;
126 }
127 var minVal = this.nextRange.minValue;
128 var maxValue = minVal + this.options.rangeSize - 1;
129 if (maxValue >= this.file.size) {
130 maxValue = this.file.size - 1;
131 }
132 return new Range_1.Range(minVal, maxValue);
133 };
134 /**
135 * @deprecated This function has been moved into FileObject interface.
136 * @public
137 * Slices the file content to the given range
138 * @param {Range} range - The range value
139 * @returns The sliced ArrayBuffer or Blob
140 */
141 LargeFileUploadTask.prototype.sliceFile = function (range) {
142 console.warn("The LargeFileUploadTask.sliceFile() function has been deprecated and moved into the FileObject interface.");
143 if (this.file.content instanceof ArrayBuffer || this.file.content instanceof Blob || this.file.content instanceof Uint8Array) {
144 return this.file.content.slice(range.minValue, range.maxValue + 1);
145 }
146 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.");
147 };
148 /**
149 * @public
150 * @async
151 * Uploads file to the server in a sequential order by slicing the file
152 * @returns The promise resolves to uploaded response
153 */
154 LargeFileUploadTask.prototype.upload = function () {
155 return tslib_1.__awaiter(this, void 0, void 0, function () {
156 var uploadEventHandlers, nextRange, err, fileSlice, rawResponse, responseBody, res;
157 return tslib_1.__generator(this, function (_a) {
158 switch (_a.label) {
159 case 0:
160 uploadEventHandlers = this.options && this.options.uploadEventHandlers;
161 _a.label = 1;
162 case 1:
163 if (!!this.uploadSession.isCancelled) return [3 /*break*/, 5];
164 nextRange = this.getNextRange();
165 if (nextRange.maxValue === -1) {
166 err = new Error("Task with which you are trying to upload is already completed, Please check for your uploaded file");
167 err.name = "Invalid Session";
168 throw err;
169 }
170 return [4 /*yield*/, this.file.sliceFile(nextRange)];
171 case 2:
172 fileSlice = _a.sent();
173 return [4 /*yield*/, this.uploadSliceGetRawResponse(fileSlice, nextRange, this.file.size)];
174 case 3:
175 rawResponse = _a.sent();
176 if (!rawResponse) {
177 throw new GraphClientError_1.GraphClientError("Something went wrong! Large file upload slice response is null.");
178 }
179 return [4 /*yield*/, GraphResponseHandler_1.GraphResponseHandler.getResponse(rawResponse)];
180 case 4:
181 responseBody = _a.sent();
182 /**
183 * (rawResponse.status === 201) -> This condition is applicable for OneDrive, PrintDocument and Outlook APIs.
184 * (rawResponse.status === 200 && responseBody.id) -> This additional condition is applicable only for OneDrive API.
185 */
186 if (rawResponse.status === 201 || (rawResponse.status === 200 && responseBody.id)) {
187 this.reportProgress(uploadEventHandlers, nextRange);
188 return [2 /*return*/, UploadResult_1.UploadResult.CreateUploadResult(responseBody, rawResponse.headers)];
189 }
190 res = {
191 expirationDateTime: responseBody.expirationDateTime || responseBody.ExpirationDateTime,
192 nextExpectedRanges: responseBody.NextExpectedRanges || responseBody.nextExpectedRanges,
193 };
194 this.updateTaskStatus(res);
195 this.reportProgress(uploadEventHandlers, nextRange);
196 return [3 /*break*/, 1];
197 case 5: return [2 /*return*/];
198 }
199 });
200 });
201 };
202 LargeFileUploadTask.prototype.reportProgress = function (uploadEventHandlers, nextRange) {
203 if (uploadEventHandlers && uploadEventHandlers.progress) {
204 uploadEventHandlers.progress(nextRange, uploadEventHandlers.extraCallbackParam);
205 }
206 };
207 /**
208 * @public
209 * @async
210 * Uploads given slice to the server
211 * @param {ArrayBuffer | Blob | File} fileSlice - The file slice
212 * @param {Range} range - The range value
213 * @param {number} totalSize - The total size of a complete file
214 * @returns The response body of the upload slice result
215 */
216 LargeFileUploadTask.prototype.uploadSlice = function (fileSlice, range, totalSize) {
217 return tslib_1.__awaiter(this, void 0, void 0, function () {
218 return tslib_1.__generator(this, function (_a) {
219 switch (_a.label) {
220 case 0: return [4 /*yield*/, this.client
221 .api(this.uploadSession.url)
222 .headers({
223 "Content-Length": "".concat(range.maxValue - range.minValue + 1),
224 "Content-Range": "bytes ".concat(range.minValue, "-").concat(range.maxValue, "/").concat(totalSize),
225 "Content-Type": "application/octet-stream",
226 })
227 .put(fileSlice)];
228 case 1: return [2 /*return*/, _a.sent()];
229 }
230 });
231 });
232 };
233 /**
234 * @public
235 * @async
236 * Uploads given slice to the server
237 * @param {unknown} fileSlice - The file slice
238 * @param {Range} range - The range value
239 * @param {number} totalSize - The total size of a complete file
240 * @returns The raw response of the upload slice result
241 */
242 LargeFileUploadTask.prototype.uploadSliceGetRawResponse = function (fileSlice, range, totalSize) {
243 return tslib_1.__awaiter(this, void 0, void 0, function () {
244 return tslib_1.__generator(this, function (_a) {
245 switch (_a.label) {
246 case 0: return [4 /*yield*/, this.client
247 .api(this.uploadSession.url)
248 .headers({
249 "Content-Length": "".concat(range.maxValue - range.minValue + 1),
250 "Content-Range": "bytes ".concat(range.minValue, "-").concat(range.maxValue, "/").concat(totalSize),
251 "Content-Type": "application/octet-stream",
252 })
253 .responseType(ResponseType_1.ResponseType.RAW)
254 .put(fileSlice)];
255 case 1: return [2 /*return*/, _a.sent()];
256 }
257 });
258 });
259 };
260 /**
261 * @public
262 * @async
263 * Deletes upload session in the server
264 * @returns The promise resolves to cancelled response
265 */
266 LargeFileUploadTask.prototype.cancel = function () {
267 return tslib_1.__awaiter(this, void 0, void 0, function () {
268 var cancelResponse;
269 return tslib_1.__generator(this, function (_a) {
270 switch (_a.label) {
271 case 0: return [4 /*yield*/, this.client
272 .api(this.uploadSession.url)
273 .responseType(ResponseType_1.ResponseType.RAW)
274 .delete()];
275 case 1:
276 cancelResponse = _a.sent();
277 if (cancelResponse.status === 204) {
278 this.uploadSession.isCancelled = true;
279 }
280 return [2 /*return*/, cancelResponse];
281 }
282 });
283 });
284 };
285 /**
286 * @public
287 * @async
288 * Gets status for the upload session
289 * @returns The promise resolves to the status enquiry response
290 */
291 LargeFileUploadTask.prototype.getStatus = function () {
292 return tslib_1.__awaiter(this, void 0, void 0, function () {
293 var response;
294 return tslib_1.__generator(this, function (_a) {
295 switch (_a.label) {
296 case 0: return [4 /*yield*/, this.client.api(this.uploadSession.url).get()];
297 case 1:
298 response = _a.sent();
299 this.updateTaskStatus(response);
300 return [2 /*return*/, response];
301 }
302 });
303 });
304 };
305 /**
306 * @public
307 * @async
308 * Resumes upload session and continue uploading the file from the last sent range
309 * @returns The promise resolves to the uploaded response
310 */
311 LargeFileUploadTask.prototype.resume = function () {
312 return tslib_1.__awaiter(this, void 0, void 0, function () {
313 return tslib_1.__generator(this, function (_a) {
314 switch (_a.label) {
315 case 0: return [4 /*yield*/, this.getStatus()];
316 case 1:
317 _a.sent();
318 return [4 /*yield*/, this.upload()];
319 case 2: return [2 /*return*/, _a.sent()];
320 }
321 });
322 });
323 };
324 /**
325 * @public
326 * @async
327 * Get the upload session information
328 * @returns The large file upload session
329 */
330 LargeFileUploadTask.prototype.getUploadSession = function () {
331 return this.uploadSession;
332 };
333 return LargeFileUploadTask;
334}());
335exports.LargeFileUploadTask = LargeFileUploadTask;
336//# sourceMappingURL=LargeFileUploadTask.js.map
\No newline at end of file