Browse Source

Drag drop of multiple files.

pull/636/head
Sebastian 5 years ago
parent
commit
7b62d2f27b
  1. 123
      frontend/app/framework/angular/forms/file-drop.directive.ts

123
frontend/app/framework/angular/forms/file-drop.directive.ts

@ -130,36 +130,65 @@ export class FileDropDirective {
return null; return null;
} }
let files: File[] = []; const files: File[] = [];
for (let i = 0; i < dataTransfer.items.length; i++) { const items = getItems(dataTransfer);
const item = dataTransfer.items[i];
// Loop over files first, otherwise Chromes deletes them in the async call.
for (const item of items) {
const file = item.getAsFile();
await transferFileTree(item, files); if (file && !!file.type && this.isAllowedFile(file)) {
files.push(file);
}
} }
files = files.filter(f => this.isAllowedFile(f)); for (const item of items) {
if (Types.isFunction(item['webkitGetAsEntry'])) {
const webkitEntry = item.webkitGetAsEntry();
return files.length > 0 ? files : null; if (webkitEntry && webkitEntry.isDirectory) {
await this.transferWebkitTree(webkitEntry, files);
}
}
} }
private hasAllowedFile(dataTransfer: DataTransfer | null) { if (files.length === 0) {
if (!dataTransfer || !hasFiles(dataTransfer)) {
return null; return null;
} }
for (let i = 0; i < dataTransfer.files.length; i++) { return files;
const file = dataTransfer.files.item(i); }
private async transferWebkitTree(item: any, files: File[]) {
if (item.isFile) {
const file = await getFilePromise(item);
if (file && this.isAllowedFile(file)) { if (file && this.isAllowedFile(file)) {
return true; files.push(file);
}
} else if (item.isDirectory) {
const entries = await getFilesPromise(item);
for (const entry of entries) {
await this.transferWebkitTree(entry, files);
}
} }
} }
for (let i = 0; i < dataTransfer.items.length; i++) { private hasAllowedFile(dataTransfer: DataTransfer | null) {
const file = dataTransfer.items[i]; if (!dataTransfer || !hasFiles(dataTransfer)) {
return null;
}
if (file && this.isAllowedFile(file)) { for (const file of getFiles(dataTransfer)) {
if (this.isAllowedFile(file)) {
return true;
}
}
for (const item of getItems(dataTransfer)) {
if (this.isAllowedFile(item)) {
return true; return true;
} }
} }
@ -196,40 +225,6 @@ function hasFiles(dataTransfer: DataTransfer): boolean {
} }
} }
async function transferWebkitTree(item: any, files: File[]) {
if (item.isFile) {
const file = await getFilePromise(item);
files.push(file);
} else if (item.isDirectory) {
const entries = await getFilesPromise(item);
for (const entry of entries) {
await transferWebkitTree(entry, files);
}
}
}
async function transferFileTree(item: DataTransferItem, files: File[]) {
if (Types.isFunction(item['webkitGetAsEntry'])) {
const webkitEntry = item.webkitGetAsEntry();
if (webkitEntry) {
await transferWebkitTree(webkitEntry, files);
return;
}
}
if (Types.isFunction(item['getAsFile'])) {
const fileItem = item.getAsFile();
if (fileItem) {
files.push(fileItem);
}
}
}
function getFilesPromise(item: any): Promise<ReadonlyArray<any>> { function getFilesPromise(item: any): Promise<ReadonlyArray<any>> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
@ -252,6 +247,38 @@ function getFilePromise(item: any): Promise<File> {
}); });
} }
function getItems(dataTransfer: DataTransfer) {
const result: DataTransferItem[] = [];
if (dataTransfer.files) {
for (let i = 0; i < dataTransfer.items.length; i++) {
const item = dataTransfer.items[i];
if (item) {
result.push(item);
}
}
}
return result;
}
function getFiles(dataTransfer: DataTransfer) {
const result: File[] = [];
if (dataTransfer.files) {
for (let i = 0; i < dataTransfer.files.length; i++) {
const file = dataTransfer.files[i];
if (file) {
result.push(file);
}
}
}
return result;
}
interface DragDropEvent extends MouseEvent { interface DragDropEvent extends MouseEvent {
readonly dataTransfer: DataTransfer; readonly dataTransfer: DataTransfer;
} }
Loading…
Cancel
Save