diff --git a/projects/ucap-webmessenger-api-common/src/lib/services/common-api.service.ts b/projects/ucap-webmessenger-api-common/src/lib/services/common-api.service.ts index 078a8743..d95167eb 100644 --- a/projects/ucap-webmessenger-api-common/src/lib/services/common-api.service.ts +++ b/projects/ucap-webmessenger-api-common/src/lib/services/common-api.service.ts @@ -219,6 +219,15 @@ export class CommonApiService { return 0 === rejected.length ? undefined : rejected; } + public checkInvalidMediaMimeForFileTalkForFileList( + fileList: FileList + ): Promise { + const files: File[] = []; + for (let i = 0; i < fileList.length; i++) { + files.push(fileList.item(i)); + } + return this.checkInvalidMediaMimeForFileTalk(files); + } public checkInvalidMediaMimeForFileTalk(files: File[]): Promise { return new Promise(async (resolve, reject) => { const mediaFiles = this.mediaFiles(files); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.ts index 510f63c8..c2fefd28 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/messages.component.ts @@ -1075,10 +1075,13 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { roomSeq: this.roomInfoSubject.value.roomSeq }; - const files: File[] = fileUploadItems.map(fui => fui.file); - const allObservables: Observable[] = []; + /** + * 확장자, real mime 체크는 이전 단계에서 진행하고 여기서는 oversize 만 체크함. + * cf) acceptableExtensionForFileTalk, checkInvalidMediaMimeForFileTalkForFileList + */ + const files: File[] = fileUploadItems.map(fui => fui.file); const fileAllowSize = !!this.sessionVerInfo && this.sessionVerInfo.fileAllowSize ? this.sessionVerInfo.fileAllowSize @@ -1105,66 +1108,6 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit { } } - // this.commonApiService.mimeCheckForImageAndVideoFiles( - // fileUploadItems.map(fui => fui.file) - // ); - - const checkExt = this.commonApiService.acceptableExtensionForFileTalk( - files.map(f => FileUtil.getExtension(f.name)) - ); - if (!!checkExt) { - if (!!this.fileUploadQueue) { - this.fileUploadQueue.onUploadComplete(); - } - - this.snackBarService.openFromComponent< - AlertSnackbarComponent, - AlertSnackbarData - >(AlertSnackbarComponent, { - duration: 1000, - verticalPosition: 'bottom', - horizontalPosition: 'center', - data: { - html: this.translateService.instant( - 'common.file.errors.notSupporedType', - { - supporedType: checkExt.join(',') - } - ) - } - }); - - return; - } - - const fakeMedias = await this.commonApiService.checkInvalidMediaMimeForFileTalk( - files - ); - if (!!fakeMedias) { - if (!!this.fileUploadQueue) { - this.fileUploadQueue.onUploadComplete(); - } - - this.snackBarService.openFromComponent< - AlertSnackbarComponent, - AlertSnackbarData - >(AlertSnackbarComponent, { - duration: 3000, - verticalPosition: 'bottom', - horizontalPosition: 'center', - data: { - html: this.translateService.instant( - 'common.file.errors.notAcceptableMime', - { - supporedType: fakeMedias.length > 0 ? fakeMedias.join(',') : '' - } - ) - } - }); - - return; - } - for (const fileUploadItem of fileUploadItems) { let thumbnail: File; if ( diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts index d5a551e6..80c5b35e 100644 --- a/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts +++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts @@ -5,11 +5,21 @@ import { EventEmitter, ViewChild, ElementRef, - Input + Input, + NgZone } from '@angular/core'; import { NgForm } from '@angular/forms'; import { FileUploadItem } from '@ucap-webmessenger/api'; -import { FileUploadQueueComponent } from '@ucap-webmessenger/ui'; +import { + FileUploadQueueComponent, + SnackBarService, + AlertSnackbarComponent, + AlertSnackbarData +} from '@ucap-webmessenger/ui'; +import { CommonApiService } from '@ucap-webmessenger/api-common'; +import { NGXLogger } from 'ngx-logger'; +import { FileUtil } from '@ucap-webmessenger/core'; +import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'ucap-chat-form', @@ -43,7 +53,13 @@ export class FormComponent implements OnInit { @ViewChild('fileInput', { static: false }) fileInput: ElementRef; - constructor() {} + constructor( + private translateService: TranslateService, + private commonApiService: CommonApiService, + private snackBarService: SnackBarService, + private readonly ngZone: NgZone, + private logger: NGXLogger + ) {} ngOnInit() {} @@ -64,17 +80,27 @@ export class FormComponent implements OnInit { } onChangeFileInput() { - const fileUploadItems = FileUploadItem.fromFiles( - this.fileInput.nativeElement.files - ); + const self = this; + const fileList = this.fileInput.nativeElement.files; + this.validUploadFile(fileList) + .then(async result => { + if (!result) { + self.fileInput.nativeElement.value = ''; + return; + } else { + const fileUploadItems = FileUploadItem.fromFiles(fileList); - if (!!this.fileUploadQueue) { - this.fileUploadQueue.onFileSelected(fileUploadItems); - } - - this.sendFiles.emit(fileUploadItems); - - this.fileInput.nativeElement.value = ''; + if (!!self.fileUploadQueue) { + self.fileUploadQueue.onFileSelected(fileUploadItems); + } + self.fileInput.nativeElement.value = ''; + self.sendFiles.emit(fileUploadItems); + } + }) + .catch(err => { + self.fileInput.nativeElement.value = ''; + this.logger.error(err); + }); } onClickStickerSelector() { @@ -90,4 +116,62 @@ export class FormComponent implements OnInit { this.clipboardPaste.emit(event); } + + async validUploadFile(fileList: FileList): Promise { + let valid = true; + + const checkExt = this.commonApiService.acceptableExtensionForFileTalk( + FileUtil.getExtensions(fileList) + ); + if (!!checkExt) { + this.ngZone.run(() => { + this.snackBarService.openFromComponent< + AlertSnackbarComponent, + AlertSnackbarData + >(AlertSnackbarComponent, { + duration: 1000, + verticalPosition: 'bottom', + horizontalPosition: 'center', + data: { + html: this.translateService.instant( + 'common.file.errors.notSupporedType', + { + supporedType: checkExt.join(',') + } + ) + } + }); + }); + valid = false; + return valid; + } + + const fakeMedia = await this.commonApiService.checkInvalidMediaMimeForFileTalkForFileList( + fileList + ); + if (!!fakeMedia) { + this.ngZone.run(() => { + this.snackBarService.openFromComponent< + AlertSnackbarComponent, + AlertSnackbarData + >(AlertSnackbarComponent, { + duration: 1000, + verticalPosition: 'bottom', + horizontalPosition: 'center', + data: { + html: this.translateService.instant( + 'common.file.errors.notAcceptableMime', + { + supporedType: fakeMedia.join(',') + } + ) + } + }); + }); + valid = false; + return valid; + } + + return valid; + } } diff --git a/projects/ucap-webmessenger-ui-message/src/lib/components/write.component.ts b/projects/ucap-webmessenger-ui-message/src/lib/components/write.component.ts index 6938aaea..20a4a981 100644 --- a/projects/ucap-webmessenger-ui-message/src/lib/components/write.component.ts +++ b/projects/ucap-webmessenger-ui-message/src/lib/components/write.component.ts @@ -173,37 +173,41 @@ export class WriteComponent implements OnInit, OnDestroy, AfterViewInit { const self = this; this.fileInput.nativeElement.onchange = async () => { const fileList: FileList = self.fileInput.nativeElement.files; + this.validUploadFile(fileList) + .then(async result => { + if (!result) { + return; + } else { + for (let i = 0; i < fileList.length; i++) { + const file = fileList.item(i); - if (!this.validUploadFile(fileList)) { - return; - } + const dataUrl = await FileUtil.fromBlobToDataUrl(file); + const img = document.createElement('img'); + img.src = dataUrl as string; + img.setAttribute('style', 'max-height:250px; max-width:250px;'); + img[ATTR_FILE] = file; + self.insertNode(img); - this.validUploadFile(fileList).then(async result => { - if (!result) { - return; - } else { - for (let i = 0; i < fileList.length; i++) { - const file = fileList.item(i); + const empty = document.createElement('div'); + empty.innerHTML = ' 
'; + self.insertNode(empty, true); + } - const dataUrl = await FileUtil.fromBlobToDataUrl(file); - const img = document.createElement('img'); - img.src = dataUrl as string; - img.setAttribute('style', 'max-height:250px; max-width:250px;'); - img[ATTR_FILE] = file; - self.insertNode(img); + self.fileInput.nativeElement.value = ''; + self.fileInput.nativeElement.onchange = undefined; - const empty = document.createElement('div'); - empty.innerHTML = ' 
'; - self.insertNode(empty, true); + self.checkContentLength(); + self.changeDetectorRef.detectChanges(); } - + }) + .catch(err => { self.fileInput.nativeElement.value = ''; self.fileInput.nativeElement.onchange = undefined; self.checkContentLength(); self.changeDetectorRef.detectChanges(); - } - }); + this.logger.error(err); + }); }; } @@ -213,24 +217,28 @@ export class WriteComponent implements OnInit, OnDestroy, AfterViewInit { const self = this; this.fileInput.nativeElement.onchange = () => { const fileList: FileList = this.fileInput.nativeElement.files; - - if (!this.validUploadFile(fileList)) { - self.fileInput.nativeElement.value = ''; - return; - } - - if (!self.attachmentList) { - self.attachmentList = []; - } - - for (let i = 0; i < fileList.length; i++) { - const file = fileList.item(i); - self.attachmentList.push(file); - } - - self.changeDetectorRef.detectChanges(); - - self.fileInput.nativeElement.value = ''; + this.validUploadFile(fileList) + .then(async result => { + if (!result) { + self.fileInput.nativeElement.value = ''; + return; + } else { + if (!self.attachmentList) { + self.attachmentList = []; + } + for (let i = 0; i < fileList.length; i++) { + const file = fileList.item(i); + self.attachmentList.push(file); + } + self.fileInput.nativeElement.value = ''; + self.changeDetectorRef.detectChanges(); + } + }) + .catch(err => { + self.fileInput.nativeElement.value = ''; + self.changeDetectorRef.detectChanges(); + this.logger.error(err); + }); }; } @@ -289,12 +297,8 @@ export class WriteComponent implements OnInit, OnDestroy, AfterViewInit { return valid; } - const files: File[] = []; - for (let i = 0; i < fileList.length; i++) { - files.push(fileList.item(i)); - } - const fakeMedia = await this.commonApiService.checkInvalidMediaMimeForFileTalk( - files + const fakeMedia = await this.commonApiService.checkInvalidMediaMimeForFileTalkForFileList( + fileList ); if (!!fakeMedia) { this.ngZone.run(() => { diff --git a/projects/ucap-webmessenger-ui/src/lib/directives/file-upload-for.directive.ts b/projects/ucap-webmessenger-ui/src/lib/directives/file-upload-for.directive.ts index c7acba9e..082bfe9b 100644 --- a/projects/ucap-webmessenger-ui/src/lib/directives/file-upload-for.directive.ts +++ b/projects/ucap-webmessenger-ui/src/lib/directives/file-upload-for.directive.ts @@ -5,12 +5,21 @@ import { HostListener, Output, Input, - AfterViewInit + AfterViewInit, + NgZone } from '@angular/core'; import { NGXLogger } from 'ngx-logger'; import { FileUploadQueueComponent } from '../components/file-upload-queue.component'; import { FileUploadItem } from '@ucap-webmessenger/api'; +import { TranslateService } from '@ngx-translate/core'; +import { CommonApiService } from '@ucap-webmessenger/api-common'; +import { SnackBarService } from '../services/snack-bar.service'; +import { FileUtil } from '@ucap-webmessenger/core'; +import { + AlertSnackbarComponent, + AlertSnackbarData +} from '../snackbars/alert.snackbar.component'; @Directive({ selector: 'input[ucapFileUploadFor], div[ucapFileUploadFor]' @@ -33,7 +42,14 @@ export class FileUploadForDirective implements AfterViewInit { dragOver = false; - constructor(private elementRef: ElementRef, private logger: NGXLogger) {} + constructor( + private elementRef: ElementRef, + private logger: NGXLogger, + private translateService: TranslateService, + private commonApiService: CommonApiService, + private snackBarService: SnackBarService, + private readonly ngZone: NgZone + ) {} ngAfterViewInit(): void {} @@ -93,17 +109,37 @@ export class FileUploadForDirective implements AfterViewInit { if (!this.isFileDrag(event.dataTransfer)) { return; } + + const self = this; const files: FileList = event.dataTransfer.files; - const fileUploadItems = FileUploadItem.fromFiles(files); - this.fileSelected.emit(fileUploadItems); event.preventDefault(); event.stopPropagation(); this.elementRef.nativeElement.value = ''; this.dragOver = false; - if (!!this.fileUploadQueue) { - this.fileUploadQueue.onDrop(fileUploadItems); - } + + this.validUploadFile(files) + .then(async result => { + if (!result) { + if (!!this.fileUploadQueue) { + this.fileUploadQueue.onUploadComplete(); + } + return; + } else { + const fileUploadItems = FileUploadItem.fromFiles(files); + self.fileSelected.emit(fileUploadItems); + + if (!!self.fileUploadQueue) { + self.fileUploadQueue.onDrop(fileUploadItems); + } + } + }) + .catch(err => { + if (!!this.fileUploadQueue) { + this.fileUploadQueue.onUploadComplete(); + } + this.logger.error(err); + }); } private isFileDrag(dataTransfer: DataTransfer): boolean { @@ -121,4 +157,62 @@ export class FileUploadForDirective implements AfterViewInit { return true; } + + private async validUploadFile(fileList: FileList): Promise { + let valid = true; + + const checkExt = this.commonApiService.acceptableExtensionForFileTalk( + FileUtil.getExtensions(fileList) + ); + if (!!checkExt) { + this.ngZone.run(() => { + this.snackBarService.openFromComponent< + AlertSnackbarComponent, + AlertSnackbarData + >(AlertSnackbarComponent, { + duration: 1000, + verticalPosition: 'bottom', + horizontalPosition: 'center', + data: { + html: this.translateService.instant( + 'common.file.errors.notSupporedType', + { + supporedType: checkExt.join(',') + } + ) + } + }); + }); + valid = false; + return valid; + } + + const fakeMedia = await this.commonApiService.checkInvalidMediaMimeForFileTalkForFileList( + fileList + ); + if (!!fakeMedia) { + this.ngZone.run(() => { + this.snackBarService.openFromComponent< + AlertSnackbarComponent, + AlertSnackbarData + >(AlertSnackbarComponent, { + duration: 1000, + verticalPosition: 'bottom', + horizontalPosition: 'center', + data: { + html: this.translateService.instant( + 'common.file.errors.notAcceptableMime', + { + supporedType: fakeMedia.join(',') + } + ) + } + }); + }); + valid = false; + return valid; + } + + return valid; + } }