目前我正在使用Ngx-dropzone-Wrapper插件上传文件。
但是现在我想在Dropzone插件中添加文件夹选择器。
所以有没有办法添加dropzone文件夹选择选项与webkitdirectory api或不同的方式。
如果没有,那么任何其他支持文件夹上传的dropzone +具有分块选项。
Thanks in advance😋
我可以和你分享我自己的解决方案。
首先,我不使用第三方库,所以让我们从一个简单的拖放指令开始。
@Directive({
selector: '[appUploadDragAndDrop]',
})
export class UploadDragAndDropDirective {
constructor(private el: ElementRef, private r2: Renderer2, private uploadSbService: UploadSnackbarService) {}
@HostListener('dragover', ['$event']) onDragOver(e: DragEvent): void {
e.preventDefault();
e.stopPropagation();
}
@HostListener('dragenter', ['$event']) onDragEnter(e: DragEvent): void {
e.preventDefault();
e.stopPropagation();
this.r2.addClass(this.el.nativeElement, 'upload-blackout');
}
@HostListener('dragleave', ['$event']) onDragLeave(e: DragEvent): void {
e.preventDefault();
e.stopPropagation();
this.r2.removeClass(this.el.nativeElement, 'upload-blackout');
}
@HostListener('drop', ['$event']) onDrop(e: DragEvent): void {
e.preventDefault();
e.stopPropagation();
const files = e.dataTransfer?.files;
if (files && files.length > 0) {
console.log(Array.from(files));
}
}
}
现在我们可以删除文件了,但是如果我们还想处理这个文件夹呢?我们应该将这个方法(webkitGetAsEntry)应用到我们的解决方案中。
我们会得到一些像
export class UploadDragAndDropDirective {
constructor(private el: ElementRef, private r2: Renderer2, private uploadSbService: UploadSnackbarService) {}
@HostListener('dragover', ['$event']) onDragOver(e: DragEvent): void {
e.preventDefault();
e.stopPropagation();
}
@HostListener('dragenter', ['$event']) onDragEnter(e: DragEvent): void {
e.preventDefault();
e.stopPropagation();
this.r2.addClass(this.el.nativeElement, 'upload-blackout');
}
@HostListener('dragleave', ['$event']) onDragLeave(e: DragEvent): void {
e.preventDefault();
e.stopPropagation();
this.r2.removeClass(this.el.nativeElement, 'upload-blackout');
}
@HostListener('drop', ['$event']) onDrop(e: any): void {
e.preventDefault();
e.stopPropagation();
const items = e.dataTransfer.items;
this.getFilesDataTransferItems(items).subscribe(array => console.log(this.flatten(array)));
}
private flatten(arr: any[]): [] {
return arr.reduce((flat, toFlatten) => (flat.concat(Array.isArray(toFlatten) ? this.flatten(toFlatten) : toFlatten)), []);
}
private getFilesDataTransferItems(dataTransferItems: DataTransferItemList): Observable<unknown[]> {
const traverseFileTreePromise =
(item: any, path: string | null = ''): Observable<unknown> => new Observable<unknown>(resolve => {
if (item.isFile) {
item.file((file: File) => {
resolve.next(file);
});
} else if (item.isDirectory) {
const dirReader = item.createReader();
dirReader.readEntries((entries: any[]) => {
const entriesPromises = [];
for (const entr of entries)
{entriesPromises.push(
traverseFileTreePromise(entr, path || '' + item.name + '/')
);}
zip(entriesPromises).pipe(tap((data) => resolve.next(data))).subscribe();
});
}
});
return new Observable(resolve => {
const entriesPromises = [];
for (let i = 0; i < dataTransferItems.length; i++) {
const fileEntry = dataTransferItems[i].webkitGetAsEntry();
if (fileEntry) {
entriesPromises.push(traverseFileTreePromise(fileEntry, null));
}
}
zip(entriesPromises).pipe(tap((data) => resolve.next(data))).subscribe();
});
}
}