azure-adls-uploader
Version:
Azure ADLS Uploader for client web apps
166 lines • 6.86 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Uploader = void 0;
const storage_file_datalake_1 = require("@azure/storage-file-datalake");
class Uploader {
constructor(config) {
this._abortController = new AbortController();
this._progress = 0;
this._size = 0;
this._uploadedBytes = 0;
this._isUploading = false;
this._queue = [];
this.config = {
getItemUploadUrl: config.getItemUploadUrl,
chunkSize: this.isPositiveInteger(config.chunkSize) ? config.chunkSize : 1024 * 1024 * 100,
chunkUploadRetries: this.isPositiveInteger(config.chunkUploadRetries) ? config.chunkUploadRetries : 5,
onItemStart: config.onItemStart || (() => { }),
onItemProgress: config.onItemProgress || (() => { }),
onItemComplete: config.onItemComplete || (() => { }),
onItemError: config.onItemError || (() => { }),
onStart: config.onStart || (() => { }),
onProgress: config.onProgress || (() => { }),
onComplete: config.onComplete || (() => { })
};
}
uploadItem(item) {
return __awaiter(this, void 0, void 0, function* () {
try {
item.isUploading = true;
yield this.config.onItemStart(item);
yield this.uploadFile(item);
item.isUploading = false;
yield this.config.onItemComplete(item);
}
catch (err) {
item.isUploading = false;
this.config.onItemError(item, err);
}
});
}
uploadFile(item) {
return __awaiter(this, void 0, void 0, function* () {
let fileClient = yield this.getFileClient(item);
yield (fileClient === null || fileClient === void 0 ? void 0 : fileClient.create());
let retries = 1;
while (item.uploadedBytes < item.file.size) {
if (!this._isUploading)
return;
try {
yield this.uploadChunk(fileClient, item);
retries = 0;
}
catch (err) {
if (retries < this.config.chunkUploadRetries) {
retries++;
}
else {
throw err;
}
}
fileClient = yield this.getFileClient(item);
}
yield (fileClient === null || fileClient === void 0 ? void 0 : fileClient.flush(item.file.size, { close: true, pathHttpHeaders: { contentType: item.file.type } }));
});
}
getFileClient(item) {
return __awaiter(this, void 0, void 0, function* () {
if (!this._isUploading)
return;
const uploadUrl = yield this.config.getItemUploadUrl(item);
return new storage_file_datalake_1.DataLakeFileClient(uploadUrl);
});
}
uploadChunk(client, item) {
return __awaiter(this, void 0, void 0, function* () {
const blob = item.file.slice(item.uploadedBytes, Math.min(item.uploadedBytes + this.config.chunkSize, item.file.size));
yield (client === null || client === void 0 ? void 0 : client.append(blob, item.uploadedBytes, blob.size, {
onProgress: this.onUploadProgress.bind(this, item),
abortSignal: this._abortController.signal
}));
});
}
onUploadProgress(item, progress) {
this._uploadedBytes += progress.loadedBytes - item.uploadedBytes;
this._progress = this._uploadedBytes / this._size * 100;
item.uploadedBytes += progress.loadedBytes - item.uploadedBytes;
item.progress = item.uploadedBytes / item.file.size * 100;
this.config.onItemProgress(item);
this.config.onProgress(this._progress);
}
isPositiveInteger(value) {
return !!value && Number.isInteger(value) && value > 0;
}
get queue() {
return this._queue;
}
get isUploading() {
return this._isUploading;
}
get size() {
return this._size;
}
get uploadedBytes() {
return this._uploadedBytes;
}
get progress() {
return this._progress;
}
addFiles(files) {
Array.from(files).forEach(this.addFile.bind(this));
}
addFile(file) {
if (this._queue.some(item => item.file.name === file.name))
return;
this._queue.push({ file, uploadedBytes: 0, progress: 0, isUploading: false });
this._size += file.size;
}
removeItem(item) {
this.removeFile(item.file);
}
removeFile(file) {
const item = this._queue.find(i => i.file.name === file.name && !i.isUploading);
if (!item)
return;
this._queue = this._queue.filter(i => i.file.name !== item.file.name);
this._size -= item.file.size;
}
clearQueue() {
this._queue = this._queue.filter(i => i.isUploading);
this._size = this._queue.reduce((acc, item) => acc + item.file.size, 0);
}
cancel() {
this._abortController.abort();
const uplItem = this._queue.find(i => i.isUploading);
if (uplItem)
uplItem.isUploading = false;
this._isUploading = false;
}
upload() {
return __awaiter(this, void 0, void 0, function* () {
const items = Array.from(this._queue);
this._isUploading = true;
yield this.config.onStart();
for (const item of items) {
if (!this._isUploading)
return;
if (item.progress === 100)
continue;
yield this.uploadItem(item);
}
this._isUploading = false;
yield this.config.onComplete();
});
}
}
exports.Uploader = Uploader;
//# sourceMappingURL=uploader.js.map