ngx-uploader-directive
Version:
Angular File Uploader Directive which provides two directives, which are select and file drag and drop to upload files on server.
1,209 lines (1,199 loc) • 48.9 kB
JavaScript
import { EventEmitter, Directive, ElementRef, Input, Output, HostListener, NgModule } from '@angular/core';
import { HttpErrorResponse, HttpRequest, HttpHeaders, HttpEventType, HttpClient, HttpClientModule } from '@angular/common/http';
import { Subject, Observable } from 'rxjs';
import { mergeMap, finalize } from 'rxjs/operators';
/**
* @fileoverview added by tsickle
* Generated from: lib/configs/config.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const environment = {
production: true
};
/**
* @fileoverview added by tsickle
* Generated from: lib/models/ngx-uploader-directive-models.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @license
* The MIT License (MIT)
* Copyright (c) 2015-2018 Jan Kuri jan@bleenco.com
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* File Upload Options.
* @record
*/
function IUploadOptions() { }
if (false) {
/** @type {?} */
IUploadOptions.prototype.requestConcurrency;
/** @type {?} */
IUploadOptions.prototype.maxFilesToAddInSingleRequest;
/** @type {?|undefined} */
IUploadOptions.prototype.allowedFileTypes;
/** @type {?|undefined} */
IUploadOptions.prototype.maxFileUploads;
/** @type {?|undefined} */
IUploadOptions.prototype.maxFileSize;
/** @type {?|undefined} */
IUploadOptions.prototype.logs;
}
/**
* Selected File Object.
* @record
*/
function ISelectedFile() { }
if (false) {
/** @type {?} */
ISelectedFile.prototype.requestId;
/** @type {?} */
ISelectedFile.prototype.fileIndex;
/** @type {?} */
ISelectedFile.prototype.name;
/** @type {?} */
ISelectedFile.prototype.type;
/** @type {?} */
ISelectedFile.prototype.selectedEventType;
/** @type {?|undefined} */
ISelectedFile.prototype.progress;
/** @type {?|undefined} */
ISelectedFile.prototype.nativeFile;
/** @type {?|undefined} */
ISelectedFile.prototype.response;
}
/**
* File Upload Progress.
* @record
*/
function IUploadProgress() { }
if (false) {
/** @type {?} */
IUploadProgress.prototype.status;
/** @type {?|undefined} */
IUploadProgress.prototype.data;
}
/**
* Upload Input events that can be emit to ngx-uploader-directive.
* @record
*/
function IUploadInput() { }
if (false) {
/** @type {?} */
IUploadInput.prototype.type;
/**
* Input unique reference number to evalueate unique events.
* Generate using Math.random().
* @type {?|undefined}
*/
IUploadInput.prototype.inputReferenceNumber;
/** @type {?|undefined} */
IUploadInput.prototype.url;
/** @type {?|undefined} */
IUploadInput.prototype.method;
/** @type {?|undefined} */
IUploadInput.prototype.requestId;
/** @type {?|undefined} */
IUploadInput.prototype.fieldName;
/** @type {?|undefined} */
IUploadInput.prototype.fileIndex;
/** @type {?|undefined} */
IUploadInput.prototype.file;
/** @type {?|undefined} */
IUploadInput.prototype.data;
/** @type {?|undefined} */
IUploadInput.prototype.headers;
}
/**
* File Upload Output Events that emitted by ngx-uploader-directive.
* @record
*/
function IUploadOutput() { }
if (false) {
/** @type {?} */
IUploadOutput.prototype.type;
/** @type {?|undefined} */
IUploadOutput.prototype.requestId;
/** @type {?|undefined} */
IUploadOutput.prototype.files;
/** @type {?|undefined} */
IUploadOutput.prototype.fileSelectedEventType;
/** @type {?|undefined} */
IUploadOutput.prototype.progress;
/** @type {?|undefined} */
IUploadOutput.prototype.response;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/services/ngx-uploader-directive.service.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// @Injectable({
// providedIn: 'root'
// })
class NgxUploaderDirectiveService {
/**
* @param {?=} requestConcurrency
* @param {?=} maxFilesToAddInSingleRequest
* @param {?=} fileTypes
* @param {?=} maxFileUploads
* @param {?=} maxFileSize
* @param {?=} httpClient
* @param {?=} logs
*/
constructor(requestConcurrency = Number.POSITIVE_INFINITY, maxFilesToAddInSingleRequest = Number.POSITIVE_INFINITY, fileTypes = ['*'], maxFileUploads = Number.POSITIVE_INFINITY, maxFileSize = Number.POSITIVE_INFINITY, httpClient, logs) {
this.httpClient = httpClient;
this.logs = logs;
this.devEnv = !environment.production;
this.queue = new Array();
this.MaxNumberOfRequest = 10;
this.fileServiceEvents = new EventEmitter();
this.uploadScheduler = new Subject();
this.maxFilesToAddInSingleRequest = 0;
this.fileTypes = fileTypes;
this.maxFileUploads = maxFileUploads;
this.maxFilesToAddInSingleRequest = maxFilesToAddInSingleRequest;
this.maxFileSize = maxFileSize;
this.subscriptions = new Array();
this.uploadScheduler
.pipe(mergeMap((/**
* @param {?} upload
* @return {?}
*/
upload => this.startUpload(upload)), requestConcurrency === 0 ? this.MaxNumberOfRequest : requestConcurrency))
.subscribe((/**
* @param {?} uploadOutput
* @return {?}
*/
uploadOutput => this.fileServiceEvents.emit(uploadOutput)));
}
/**
* Handles uploaded files
* @param {?} selectedFiles Selected Files
* @param {?} selectedEventType
* @return {?}
*/
handleSelectedFiles(selectedFiles, selectedEventType) {
this.queue = new Array();
this.fileServiceEvents.emit({ type: 'init', fileSelectedEventType: selectedEventType });
if (selectedFiles.length > this.maxFileUploads) {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Maxium ' + this.maxFileUploads + ' files can be upload' });
this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: selectedEventType });
return;
}
// verify files with allowed files and max uploads
/** @type {?} */
const allowedFiles = new Array();
/** @type {?} */
const rejectedFiles = new Array();
// tslint:disable-next-line: prefer-for-of
for (let checkingFileIndex = 0; checkingFileIndex < selectedFiles.length; checkingFileIndex++) {
/** @type {?} */
const checkingFile = selectedFiles[checkingFileIndex];
/** @type {?} */
const queueLength = allowedFiles.length + this.queue.length + 1;
if (this.isFileTypeAllowed(checkingFile.type) && this.isFileSizeAllowed(checkingFile.size)) {
allowedFiles.push(checkingFile);
}
else {
/** @type {?} */
const rejectedFile = this.convertToSelectedFile(checkingFile, checkingFileIndex, this.generateRandomeId(), selectedEventType);
rejectedFiles.push(rejectedFile);
}
}
if (rejectedFiles.length > 0) {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Invalid file type or file size exceeded the limit ' + this.humanizeBytes(this.maxFileSize), statusText: 'Invalid Input' });
this.fileServiceEvents.emit({ type: 'rejected', files: rejectedFiles, fileSelectedEventType: selectedEventType, response: this.httpErrorResponse });
}
if (this.logs) {
console.info('Allowed Files', allowedFiles);
}
// Adding files to queue
/** @type {?} */
let filesAddedToQueue;
/** @type {?} */
const totalFilesAdded = new Array();
if (this.maxFilesToAddInSingleRequest === 0 || this.maxFilesToAddInSingleRequest === 1) {
/** @type {?} */
const eventId = this.generateRandomeId();
// tslint:disable-next-line: prefer-for-of
for (let fileIndex = 0; fileIndex < allowedFiles.length; fileIndex++) {
/** @type {?} */
const file = allowedFiles[fileIndex];
/** @type {?} */
let selectedFile;
if (this.maxFilesToAddInSingleRequest === 0) {
selectedFile = this.convertToSelectedFile(file, fileIndex, eventId, selectedEventType);
}
else if (this.maxFilesToAddInSingleRequest === 1) {
selectedFile = this.convertToSelectedFile(file, fileIndex, this.generateRandomeId(), selectedEventType);
}
this.queue.push(selectedFile);
filesAddedToQueue = new Array();
filesAddedToQueue.push(selectedFile);
totalFilesAdded.push(selectedFile);
this.fileServiceEvents.emit({ type: 'addedToQueue', files: filesAddedToQueue, requestId: selectedFile.requestId, fileSelectedEventType: selectedEventType });
}
}
else {
// generate id for max files to add in single request.
/** @type {?} */
const chunkedArray = this.chunkArray(allowedFiles, this.maxFilesToAddInSingleRequest);
/** @type {?} */
let fileIndex = 0;
// tslint:disable-next-line: prefer-for-of
for (let chukedQueueArrayIndex = 0; chukedQueueArrayIndex < chunkedArray.length; chukedQueueArrayIndex++) {
/** @type {?} */
const chunkedElement = chunkedArray[chukedQueueArrayIndex];
/** @type {?} */
const eventId = this.generateRandomeId();
filesAddedToQueue = new Array();
// tslint:disable-next-line: prefer-for-of
for (let chunkElementIndex = 0; chunkElementIndex < chunkedElement.length; chunkElementIndex++) {
/** @type {?} */
const selectedFileElement = chunkedElement[chunkElementIndex];
/** @type {?} */
const convertdFile = this.convertToSelectedFile(selectedFileElement, fileIndex, eventId, selectedEventType);
this.queue.push(convertdFile);
filesAddedToQueue.push(convertdFile);
totalFilesAdded.push(convertdFile);
fileIndex += 1;
}
this.fileServiceEvents.emit({ type: 'addedToQueue', files: filesAddedToQueue, requestId: eventId, fileSelectedEventType: selectedEventType });
}
}
if (this.queue.length > 0) {
this.fileServiceEvents.emit({ type: 'allAddedToQueue', files: totalFilesAdded, fileSelectedEventType: selectedEventType });
}
if (this.logs) {
console.info('Queue', this.queue);
}
}
/**
* Handles input events upload | remove | cancel
* @param {?} inputEvnets Input events of file upload process
* @return {?}
*/
handleInputEvents(inputEvnets) {
return inputEvnets.subscribe((/**
* @param {?} event
* @return {?}
*/
(event) => {
if (this.logs && this.devEnv) {
console.info('Input event', event);
}
if (this.queue.length === 0) {
return;
}
/** @type {?} */
const requestId = event.requestId;
switch (event.type) {
case 'uploadFile':
if (!requestId) {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Invalid request id.', statusText: 'Invalid Input' });
this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' });
return;
}
this.uploadScheduler.next({
files: this.queue.filter((/**
* @param {?} file
* @return {?}
*/
(file) => {
return file.requestId === event.requestId;
})),
event
});
break;
case 'uploadAll':
/** @type {?} */
const groupOfRequests = this.groupByArray(this.queue.filter((/**
* @param {?} file
* @return {?}
*/
(file) => file.progress.status === 'Queue')), 'requestId');
if (this.logs) {
console.info('Group of request', groupOfRequests);
}
for (const request in groupOfRequests) {
if (groupOfRequests.hasOwnProperty(request)) {
/** @type {?} */
const requestFiles = groupOfRequests[request];
if (this.logs && this.devEnv) {
console.info('Requesting for id ' + request, requestFiles);
}
this.uploadScheduler.next({ files: requestFiles, event });
}
}
break;
case 'cancel':
if (!requestId) {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Invalid request id.', statusText: 'Invalid Input' });
this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' });
return;
}
/** @type {?} */
const subs = this.subscriptions.filter((/**
* @param {?} sub
* @return {?}
*/
sub => sub.id === requestId));
if (this.logs && this.devEnv) {
console.info('subscriptions ', subs);
}
subs.forEach((/**
* @param {?} sub
* @return {?}
*/
sub => {
if (sub.sub) {
sub.sub.unsubscribe();
// tslint:disable-next-line: no-shadowed-variable
/** @type {?} */
const cancelledFilesArray = this.queue.filter((/**
* @param {?} file
* @return {?}
*/
(file) => file.requestId === requestId));
if (cancelledFilesArray.length > 0) {
this.queue.forEach((/**
* @param {?} file
* @param {?} fileIndex
* @param {?} queue
* @return {?}
*/
(file, fileIndex, queue) => {
queue[fileIndex].progress.status = 'Cancelled';
}));
this.fileServiceEvents.emit({ type: 'cancelled', requestId, files: cancelledFilesArray, fileSelectedEventType: cancelledFilesArray[0].selectedEventType });
}
else {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Files not found with request id ' + requestId });
this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' });
}
}
}));
break;
case 'cancelAll':
this.subscriptions.forEach((/**
* @param {?} sub
* @return {?}
*/
sub => {
if (sub.sub) {
sub.sub.unsubscribe();
}
if (this.logs && this.devEnv) {
console.info('subscriptions ', subs);
}
/** @type {?} */
const canceldFileArray = this.queue.filter((/**
* @param {?} uploadFile
* @return {?}
*/
(uploadFile) => uploadFile.requestId === sub.id));
if (canceldFileArray.length > 0) {
this.queue.forEach((/**
* @param {?} file
* @param {?} fileIndex
* @param {?} queue
* @return {?}
*/
(file, fileIndex, queue) => {
queue[fileIndex].progress.status = 'Cancelled';
}));
this.fileServiceEvents.emit({ type: 'cancelled', files: canceldFileArray, fileSelectedEventType: canceldFileArray[0].selectedEventType });
}
else {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Files not found with request id ' + requestId, statusText: 'Invalid Input' });
this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' });
}
}));
break;
case 'remove':
if (!requestId) {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Invalid request id.', statusText: 'Invalid Input' });
this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' });
return;
}
/** @type {?} */
const filesToRemove = this.queue.filter((/**
* @param {?} file
* @return {?}
*/
(file) => file.requestId === event.requestId));
if (filesToRemove.length > 0) {
/** @type {?} */
const remainingFilesArray = this.queue.filter((/**
* @param {?} file
* @return {?}
*/
(file) => file.requestId !== event.requestId));
this.queue = remainingFilesArray;
this.fileServiceEvents.emit({ type: 'removed', requestId: event.requestId, files: filesToRemove, fileSelectedEventType: 'ALL' });
}
else {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Files not found with request id ' + requestId, statusText: 'Invalid Input' });
this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' });
}
break;
case 'removeAll':
if (this.queue.length) {
this.queue = new Array();
this.fileServiceEvents.emit({ type: 'removedAll', files: this.queue, fileSelectedEventType: 'ALL' });
}
break;
}
// Temporary taken reference number not in use any where
if (NgxUploaderDirectiveService.inputEventReferenceNumber !== event.inputReferenceNumber) {
NgxUploaderDirectiveService.inputEventReferenceNumber = event.inputReferenceNumber;
}
}));
}
/**
* Check for file type is valid or not
* @param {?} mimeType file mime type
* @return {?}
*/
isFileTypeAllowed(mimeType) {
/** @type {?} */
const allAllowed = this.fileTypes.find((/**
* @param {?} type
* @return {?}
*/
(type) => type === '*')) !== undefined;
if (allAllowed) {
return true;
}
return this.fileTypes.find((/**
* @param {?} type
* @return {?}
*/
(type) => type === mimeType)) !== undefined;
}
/**
* Start file upload
* @param {?} upload object with files and upload input event
* @return {?}
*/
startUpload(upload) {
return new Observable((/**
* @param {?} observer
* @return {?}
*/
observer => {
/** @type {?} */
const sub = this.uploadFilesHttpRequest(upload.files, upload.event)
.pipe(finalize((/**
* @return {?}
*/
() => {
if (!observer.closed) {
observer.complete();
}
})))
.subscribe((/**
* @param {?} output
* @return {?}
*/
output => {
observer.next(output);
}), (/**
* @param {?} err
* @return {?}
*/
err => {
observer.error(err);
observer.complete();
}), (/**
* @return {?}
*/
() => {
observer.complete();
}));
this.subscriptions.push({ id: upload.files[0].requestId, sub });
if (this.logs && this.devEnv) {
console.info('subscriptions ', this.subscriptions);
}
}));
}
/**
* Upload files to server
* @param {?} files Array of files input
* @param {?} event Upload inout event
* @return {?}
*/
uploadFilesHttpRequest(files, event) {
return new Observable((/**
* @param {?} observer
* @return {?}
*/
observer => {
/** @type {?} */
const time = new Date().getTime();
/** @type {?} */
let speed = 0;
/** @type {?} */
let eta = null;
/** @type {?} */
const fileList = files;
/** @type {?} */
const headers = event.headers || {};
if (this.logs && this.devEnv) {
console.info('Files to Upload', fileList);
}
if (fileList.length > 0) {
/** @type {?} */
let totalSize = 0;
files.forEach((/**
* @param {?} file
* @param {?} index
* @return {?}
*/
(file, index) => {
totalSize += file.nativeFile.size;
}));
/** @type {?} */
const formData = new FormData();
if (event.data !== undefined) {
Object.keys(event.data).forEach((/**
* @param {?} key
* @return {?}
*/
key => formData.append(key, event.data[key])));
}
if (fileList.length > 1) {
// tslint:disable-next-line: prefer-for-of
for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
/** @type {?} */
const element = files[fileIndex];
formData.append('file_' + (fileIndex + 1), fileList[fileIndex].nativeFile, fileList[fileIndex].name);
}
}
else {
formData.append('file', fileList[0].nativeFile, fileList[0].name);
}
/** @type {?} */
const cancelledFiles = this.queue.filter((/**
* @param {?} file
* @return {?}
*/
file => file.requestId === fileList[0].requestId));
if (cancelledFiles[0].progress.status === 'Cancelled') {
observer.complete();
}
observer.next({ type: 'start', requestId: files[0].requestId, files, fileSelectedEventType: files[0].selectedEventType });
/** @type {?} */
const req = new HttpRequest(event.method, event.url, formData, {
headers: new HttpHeaders(headers),
reportProgress: true
});
/** @type {?} */
const httpRequestSubscription = this.httpClient.request(req).subscribe((
// tslint:disable-next-line: no-shadowed-variable
/**
* @param {?} data
* @return {?}
*/
(data) => {
switch (data.type) {
case HttpEventType.UploadProgress:
/** @type {?} */
const percentage = Math.round((data.loaded * 100) / data.total);
/** @type {?} */
const diff = new Date().getTime() - time;
speed = Math.round(data.loaded / diff * 1000);
eta = Math.ceil((data.total - data.loaded) / speed);
// console.log('Progress: ' + this.fileUploadProgress);
/** @type {?} */
const fileProgress = {
status: 'Uploading',
data: {
percentage,
speed,
speedHuman: `${this.humanizeBytes(speed)}/s`,
startTime: null,
endTime: null,
eta,
etaHuman: this.secondsToHuman(eta)
}
};
files.forEach((/**
* @param {?} file
* @param {?} index
* @param {?} filesArray
* @return {?}
*/
(file, index, filesArray) => {
filesArray[index].progress = fileProgress;
}));
observer.next({ type: 'uploading', requestId: files[0].requestId, files, progress: fileProgress, fileSelectedEventType: files[0].selectedEventType });
break;
case HttpEventType.Response:
files[0].response = data.body;
/** @type {?} */
const progress = {
status: 'Done',
data: {
percentage: 100,
speed,
speedHuman: `${this.humanizeBytes(speed)}/s`,
startTime: null,
endTime: new Date().getTime(),
eta,
etaHuman: this.secondsToHuman(eta || 0)
}
};
files.forEach((/**
* @param {?} file
* @param {?} index
* @param {?} filesArray
* @return {?}
*/
(file, index, filesArray) => {
filesArray[index].response = data.body;
}));
observer.next({ type: 'done', requestId: files[0].requestId, response: data.body, progress, fileSelectedEventType: files[0].selectedEventType, files });
observer.complete();
break;
}
}), (/**
* @param {?} error
* @return {?}
*/
(error) => {
// console.log(error);
observer.next({ type: 'error', requestId: files[0].requestId, response: error, fileSelectedEventType: files[0].selectedEventType });
observer.complete();
}));
this.subscriptions.push({ id: files[0].requestId, sub: httpRequestSubscription });
}
else {
this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Files not available for upload', statusText: 'Invalid Input' });
observer.next({ type: 'error', requestId: files[0].requestId, response: this.httpErrorResponse });
observer.complete();
}
}));
}
/**
* Http Request to upload file(s).
* @param {?} requestMethod Request method POST | GET
* @param {?} apiUrl Url to send request
* @param {?} body FormData to passwith
* @param {?=} headers
* @return {?}
*/
httpRequest(requestMethod, apiUrl, body, headers) {
/** @type {?} */
const req = new HttpRequest(requestMethod, apiUrl, body, {
headers,
reportProgress: true
});
return this.httpClient.request(req);
}
/**
* Converting seconds to human readable
* @param {?} sec Seconds
* @return {?}
*/
secondsToHuman(sec) {
return new Date(sec * 1000).toISOString().substr(11, 8);
}
/**
* Check for max file size is allowed or not
* @param {?} fileSize file size
* @return {?}
*/
isFileSizeAllowed(fileSize) {
if (!this.maxFileSize) {
return true;
}
return fileSize <= this.maxFileSize;
}
/**
* Generate Randome file id
* @return {?}
*/
generateRandomeId() {
return '_' + Math.random().toString(36).substr(2, 9);
}
/**
* Humanize file Bytes
* @param {?} bytes file bytes
* @return {?}
*/
humanizeBytes(bytes) {
if (bytes === 0) {
return '0 Byte';
}
/** @type {?} */
const k = 1024;
/** @type {?} */
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
/** @type {?} */
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
/**
* Convert selected file to Selected file Interface
* @param {?} file Selected File
* @param {?} fileIndex File index in array
* @param {?} id
* @param {?} selectedEventType
* @return {?}
*/
convertToSelectedFile(file, fileIndex, id, selectedEventType) {
// if (this.logs && this.devEnv) {
// console.info('Converting file to Input Selected File index: ' + fileIndex, file);
// }
return {
fileIndex,
requestId: id,
name: file.name,
nativeFile: file,
type: file.type,
selectedEventType,
progress: {
status: 'Queue',
data: {
percentage: 0,
eta: 0,
speed: 0,
speedHuman: this.humanizeBytes(0),
startTime: null,
endTime: null,
etaHuman: null,
}
}
};
}
/**
* Make chunks of array.
* @param {?} array Array to make chunks.
* @param {?} chunkSize Chunk size.
* @return {?}
*/
chunkArray(array, chunkSize) {
/** @type {?} */
const chunkedArray = new Array();
/** @type {?} */
let index = 0;
/** @type {?} */
const arrayLength = array.length;
for (index = 0; index < arrayLength; index += chunkSize) {
/** @type {?} */
const myChunk = array.slice(index, index + chunkSize);
// Do something if you want with the group
chunkedArray.push(myChunk);
}
return chunkedArray;
}
/**
* Group by an Array.
* @param {?} array Array of objects
* @param {?} key key
* @return {?}
*/
groupByArray(array, key) {
return array.reduce((/**
* @param {?} previousValue
* @param {?} currentValue
* @return {?}
*/
(previousValue, currentValue) => {
(previousValue[currentValue[key]] = previousValue[currentValue[key]] || []).push(currentValue);
return previousValue;
}), {});
}
}
NgxUploaderDirectiveService.inputEventReferenceNumber = 0;
if (false) {
/** @type {?} */
NgxUploaderDirectiveService.inputEventReferenceNumber;
/**
* @type {?}
* @private
*/
NgxUploaderDirectiveService.prototype.devEnv;
/** @type {?} */
NgxUploaderDirectiveService.prototype.queue;
/** @type {?} */
NgxUploaderDirectiveService.prototype.MaxNumberOfRequest;
/** @type {?} */
NgxUploaderDirectiveService.prototype.subscriptions;
/** @type {?} */
NgxUploaderDirectiveService.prototype.fileServiceEvents;
/** @type {?} */
NgxUploaderDirectiveService.prototype.uploadScheduler;
/** @type {?} */
NgxUploaderDirectiveService.prototype.fileTypes;
/** @type {?} */
NgxUploaderDirectiveService.prototype.maxFileUploads;
/** @type {?} */
NgxUploaderDirectiveService.prototype.maxFileSize;
/** @type {?} */
NgxUploaderDirectiveService.prototype.requestConcurrency;
/** @type {?} */
NgxUploaderDirectiveService.prototype.maxFilesToAddInSingleRequest;
/** @type {?} */
NgxUploaderDirectiveService.prototype.httpErrorResponse;
/**
* @type {?}
* @private
*/
NgxUploaderDirectiveService.prototype.httpClient;
/**
* @type {?}
* @private
*/
NgxUploaderDirectiveService.prototype.logs;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/directives/ngx-uploader-drop.directive.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NgxUploaderDropDirective {
/**
* @param {?} elementRef
* @param {?} httpClient
*/
constructor(elementRef, httpClient) {
this.elementRef = elementRef;
this.httpClient = httpClient;
this.devEnv = !environment.production;
this.stopEvent = (/**
* @param {?} event
* @return {?}
*/
(event) => {
event.stopPropagation();
event.preventDefault();
});
this.uploadOutput = new EventEmitter();
}
// tslint:disable-next-line: use-life-cycle-interface
/**
* @return {?}
*/
ngOnInit() {
this.subscriptions = new Array();
/** @type {?} */
const concurrency = this.options.requestConcurrency;
/** @type {?} */
const allowedFileTypes = this.options.allowedFileTypes;
/** @type {?} */
const maxFileUploads = this.options.maxFileUploads;
/** @type {?} */
const maxFileSize = this.options.maxFileSize;
this.uploadService = new NgxUploaderDirectiveService(concurrency, this.options.maxFilesToAddInSingleRequest, allowedFileTypes, maxFileUploads, maxFileSize, this.httpClient, this.options.logs);
// file upload element
this.element = this.elementRef.nativeElement;
this.element.addEventListener('drop', this.stopEvent, false);
this.element.addEventListener('dragenter', this.stopEvent, false);
this.element.addEventListener('dragover', this.stopEvent, false);
// Adding events to subscriptions
this.subscriptions.push(this.uploadService.fileServiceEvents.subscribe((/**
* @param {?} event
* @return {?}
*/
(event) => {
if (event.fileSelectedEventType === 'DROP' || event.fileSelectedEventType === 'ALL') {
if (this.options.logs && this.devEnv) {
console.info('Output drop event', event);
}
if (event.type === 'error' || event.type === 'removedAll') {
this.element.files = null;
this.element.value = '';
}
else if (event.type === 'removed' || event.type === 'rejected') {
if (this.uploadService.queue.length === 0) {
this.element.files = null;
this.element.value = '';
}
}
this.uploadOutput.emit(event);
}
})));
if (this.uploadInput instanceof EventEmitter) {
if (this.options.logs && this.devEnv) {
console.info('Input drop Init');
}
this.subscriptions.push(this.uploadService.handleInputEvents(this.uploadInput));
}
}
// tslint:disable-next-line: use-life-cycle-interface
/**
* @return {?}
*/
ngOnDestroy() {
this.subscriptions.forEach((/**
* @param {?} sub
* @return {?}
*/
sub => sub.unsubscribe()));
}
/**
* @param {?} event
* @return {?}
*/
onDrop(event) {
event.stopPropagation();
event.preventDefault();
/** @type {?} */
const outputEvent = { type: 'drop', fileSelectedEventType: 'DROP' };
this.uploadOutput.emit(outputEvent);
this.uploadService.handleSelectedFiles(event.dataTransfer.files, 'DROP');
}
/**
* @param {?} event
* @return {?}
*/
onDragOver(event) {
if (!event) {
return;
}
/** @type {?} */
const outputEvent = { type: 'dragOver', fileSelectedEventType: 'DROP' };
this.uploadOutput.emit(outputEvent);
}
/**
* @param {?} event
* @return {?}
*/
onDragLeave(event) {
if (!event) {
return;
}
/** @type {?} */
const outputEvent = { type: 'dragOut', fileSelectedEventType: 'DROP' };
this.uploadOutput.emit(outputEvent);
}
}
NgxUploaderDropDirective.decorators = [
{ type: Directive, args: [{
// tslint:disable-next-line: directive-selector
selector: '[ngxFileDrop]'
},] }
];
/** @nocollapse */
NgxUploaderDropDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: HttpClient }
];
NgxUploaderDropDirective.propDecorators = {
options: [{ type: Input }],
uploadInput: [{ type: Input }],
uploadOutput: [{ type: Output }],
onDrop: [{ type: HostListener, args: ['drop', ['$event'],] }],
onDragOver: [{ type: HostListener, args: ['dragover', ['$event'],] }],
onDragLeave: [{ type: HostListener, args: ['dragleave', ['$event'],] }]
};
if (false) {
/**
* @type {?}
* @private
*/
NgxUploaderDropDirective.prototype.devEnv;
/** @type {?} */
NgxUploaderDropDirective.prototype.options;
/** @type {?} */
NgxUploaderDropDirective.prototype.uploadInput;
/** @type {?} */
NgxUploaderDropDirective.prototype.uploadOutput;
/** @type {?} */
NgxUploaderDropDirective.prototype.uploadService;
/** @type {?} */
NgxUploaderDropDirective.prototype.element;
/** @type {?} */
NgxUploaderDropDirective.prototype.subscriptions;
/** @type {?} */
NgxUploaderDropDirective.prototype.stopEvent;
/** @type {?} */
NgxUploaderDropDirective.prototype.elementRef;
/**
* @type {?}
* @private
*/
NgxUploaderDropDirective.prototype.httpClient;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/directives/ngx-uploader-select.directive.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NgxUploaderSelectDirective {
/**
* @param {?} elementRef
* @param {?} httpClient
*/
constructor(elementRef, httpClient) {
this.elementRef = elementRef;
this.httpClient = httpClient;
this.devEnv = !environment.production;
this.fileListener = (/**
* @return {?}
*/
() => {
// tslint:disable-next-line: no-console
if (this.element.files) {
// call service method to handle selected files
this.uploadService.handleSelectedFiles(this.element.files, 'SELECT');
}
});
this.uploadOutput = new EventEmitter();
}
// tslint:disable-next-line: use-life-cycle-interface
/**
* @return {?}
*/
ngOnInit() {
this.subscriptions = new Array();
/** @type {?} */
const concurrency = this.options.requestConcurrency;
/** @type {?} */
const allowedFileTypes = this.options.allowedFileTypes;
/** @type {?} */
const maxFileUploads = this.options.maxFileUploads;
/** @type {?} */
const maxFileSize = this.options.maxFileSize;
// tslint:disable-next-line: max-line-length
this.uploadService = new NgxUploaderDirectiveService(concurrency, this.options.maxFilesToAddInSingleRequest, allowedFileTypes, maxFileUploads, maxFileSize, this.httpClient, this.options.logs);
// file upload element
this.element = this.elementRef.nativeElement;
// Adding on change event listener
this.element.addEventListener('change', this.fileListener, false);
this.subscriptions.push(this.uploadService.fileServiceEvents.subscribe((/**
* @param {?} event
* @return {?}
*/
(event) => {
if (event.fileSelectedEventType === 'SELECT' || event.fileSelectedEventType === 'ALL') {
if (event.type === 'error' || event.type === 'removedAll') {
this.element.files = null;
this.element.value = '';
}
else if (event.type === 'removed' || event.type === 'rejected') {
if (this.uploadService.queue.length === 0) {
this.element.files = null;
this.element.value = '';
}
}
this.uploadOutput.emit(event);
}
})));
if (this.uploadInput instanceof EventEmitter) {
if (this.options.logs && this.devEnv) {
console.info('Input select Init');
}
this.subscriptions.push(this.uploadService.handleInputEvents(this.uploadInput));
}
}
// tslint:disable-next-line: use-life-cycle-interface
/**
* @return {?}
*/
ngOnDestroy() {
if (this.element) {
this.element.removeEventListener('change', this.fileListener, false);
this.subscriptions.forEach((/**
* @param {?} sub
* @return {?}
*/
sub => sub.unsubscribe()));
}
}
}
NgxUploaderSelectDirective.decorators = [
{ type: Directive, args: [{
// tslint:disable-next-line: directive-selector
selector: '[ngxFileSelect]'
},] }
];
/** @nocollapse */
NgxUploaderSelectDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: HttpClient }
];
NgxUploaderSelectDirective.propDecorators = {
options: [{ type: Input }],
uploadInput: [{ type: Input }],
uploadOutput: [{ type: Output }]
};
if (false) {
/**
* @type {?}
* @private
*/
NgxUploaderSelectDirective.prototype.devEnv;
/** @type {?} */
NgxUploaderSelectDirective.prototype.options;
/** @type {?} */
NgxUploaderSelectDirective.prototype.uploadInput;
/** @type {?} */
NgxUploaderSelectDirective.prototype.uploadOutput;
/** @type {?} */
NgxUploaderSelectDirective.prototype.uploadService;
/** @type {?} */
NgxUploaderSelectDirective.prototype.element;
/** @type {?} */
NgxUploaderSelectDirective.prototype.subscriptions;
/** @type {?} */
NgxUploaderSelectDirective.prototype.fileListener;
/** @type {?} */
NgxUploaderSelectDirective.prototype.elementRef;
/**
* @type {?}
* @private
*/
NgxUploaderSelectDirective.prototype.httpClient;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/ngx-uploader-directive.module.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NgxUploaderDirectiveModule {
}
NgxUploaderDirectiveModule.decorators = [
{ type: NgModule, args: [{
declarations: [NgxUploaderDropDirective, NgxUploaderSelectDirective],
imports: [],
exports: [
NgxUploaderDropDirective,
NgxUploaderSelectDirective,
HttpClientModule
]
},] }
];
/**
* @fileoverview added by tsickle
* Generated from: public-api.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* Generated from: ngx-uploader-directive.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { NgxUploaderDirectiveModule, NgxUploaderDirectiveService, NgxUploaderDropDirective, NgxUploaderSelectDirective, environment };
//# sourceMappingURL=ngx-uploader-directive.js.map