ddc-image-upload
Version:
Dusdusan Image Upload
204 lines (167 loc) • 6.46 kB
text/typescript
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild } from '@angular/core';
import { Headers, Response } from '@angular/http';
import { UploadMetadata } from './before-upload.interface';
import { ImageService } from './image.service';
import { Style } from './style';
export class FileHolder {
public pending: boolean = false;
public serverResponse: { status: number, response: any };
constructor(public src: string, public file: File) {
}
}
export class ImageUploadComponent implements OnInit, OnChanges {
files: FileHolder[] = [];
fileCounter: number = 0;
fileOver: boolean = false;
showFileTooLargeMessage: boolean = false;
beforeUpload: (param: UploadMetadata) => UploadMetadata | Promise<UploadMetadata> = data => data;
buttonCaption = 'Select Images';
disabled = false;
cssClass = 'img-ul';
clearButtonCaption = 'Clear';
dropBoxMessage = 'Drop your images here!';
fileTooLargeMessage;
headers: Headers | { [name: string]: any };
max = 100;
maxFileSize: number;
preview = true;
partName: string;
style: Style;
supportedExtensions: string[];
url: string;
withCredentials = false;
uploadedFiles: string[] | Array<{ url: string, fileName: string, blob?: Blob }> = [];
removed = new EventEmitter<FileHolder>();
uploadStateChanged = new EventEmitter<boolean>();
uploadFinished = new EventEmitter<FileHolder>();
previewClicked = new EventEmitter<FileHolder>();
disableSelect;
currentCounter;
private inputElement: ElementRef;
private pendingFilesCounter: number = 0;
constructor(private imageService: ImageService) {
}
ngOnInit() {
if (!this.fileTooLargeMessage) {
this.fileTooLargeMessage = 'An image was too large and was not uploaded.' + (this.maxFileSize ? (' The maximum file size is ' + this.maxFileSize / 1024) + 'KiB.' : '');
}
this.supportedExtensions = this.supportedExtensions ? this.supportedExtensions.map((ext) => 'image/' + ext) : ['image/*'];
if (this.currentCounter) {
this.fileCounter = this.currentCounter;
}
console.log(this.currentCounter);
}
deleteAll() {
this.files.forEach(f => this.removed.emit(f));
this.files = [];
this.fileCounter = 0;
if (this.inputElement) {
this.inputElement.nativeElement.value = '';
}
}
deleteFile(file: FileHolder): void {
let index = this.files.indexOf(file);
this.files.splice(index, 1);
this.fileCounter--;
if (this.inputElement) {
this.inputElement.nativeElement.value = '';
}
this.removed.emit(file);
}
previewFileClicked(file: FileHolder) {
this.previewClicked.emit(file);
}
ngOnChanges(changes) {
if (changes.uploadedFiles && changes.uploadedFiles.currentValue.length > 0) {
this.processUploadedFiles();
}
}
onFileChange(files: FileList) {
if (this.disabled) return;
let remainingSlots = this.countRemainingSlots();
let filesToUploadNum = files.length > remainingSlots ? remainingSlots : files.length;
if (this.url && filesToUploadNum != 0) {
this.uploadStateChanged.emit(true);
}
this.fileCounter += filesToUploadNum;
this.showFileTooLargeMessage = false;
this.uploadFiles(files, filesToUploadNum);
}
onFileOver = (isOver) => this.fileOver = isOver;
private countRemainingSlots = () => this.max - this.fileCounter;
private onResponse(response: Response, fileHolder: FileHolder) {
fileHolder.serverResponse = { status: response.status, response };
fileHolder.pending = false;
this.uploadFinished.emit(fileHolder);
if (--this.pendingFilesCounter == 0) {
this.uploadStateChanged.emit(false);
}
}
private processUploadedFiles() {
for (let i = 0; i < this.uploadedFiles.length; i++) {
let data: any = this.uploadedFiles[i];
let fileBlob: Blob,
file: File,
fileUrl: string;
if (data instanceof Object) {
fileUrl = data.url;
fileBlob = (data.blob) ? data.blob : new Blob([data]);
file = new File([fileBlob], data.fileName);
} else {
fileUrl = data;
fileBlob = new Blob([fileUrl]);
file = new File([fileBlob], fileUrl);
}
this.files.push(new FileHolder(fileUrl, file));
}
}
private async uploadFiles(files: FileList, filesToUploadNum: number) {
for (let i = 0; i < filesToUploadNum; i++) {
const file = files[i];
if (this.maxFileSize && file.size > this.maxFileSize) {
this.fileCounter--;
this.inputElement.nativeElement.value = '';
this.showFileTooLargeMessage = true;
this.uploadStateChanged.emit(false)
continue;
}
const beforeUploadResult: UploadMetadata = await this.beforeUpload({ file, url: this.url, abort: false });
if (beforeUploadResult.abort) {
this.fileCounter--;
this.inputElement.nativeElement.value = '';
continue;
}
const img = document.createElement('img');
img.src = window.URL.createObjectURL(beforeUploadResult.file);
const reader = new FileReader();
reader.addEventListener('load', (event: any) => {
const fileHolder: FileHolder = new FileHolder(event.target.result, beforeUploadResult.file);
this.uploadSingleFile(fileHolder, beforeUploadResult.url, beforeUploadResult.formData);
this.files.push(fileHolder);
}, false);
reader.readAsDataURL(beforeUploadResult.file);
}
}
private uploadSingleFile(fileHolder: FileHolder, url = this.url, customForm?: { [name: string]: any }) {
if (url) {
this.pendingFilesCounter++;
fileHolder.pending = true;
this.imageService
.postImage(url, fileHolder.file, this.headers, this.partName, customForm, this.withCredentials)
.subscribe(
response => this.onResponse(response, fileHolder),
error => {
this.onResponse(error, fileHolder);
this.deleteFile(fileHolder);
});
} else {
this.uploadFinished.emit(fileHolder);
}
}
}