Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Folder Upload with Angular Js

I understand that file upload is possible with Angular Js. But I researched and found no provisions for an entire folder to be uploaded. I am working on ASP.NET Core.

Is folder uploading possible with AngularJS. Alternatives are welcome as well. Also I am wondering what is the equivalent of FolderBrowserDialog in ASP.NET Core.

like image 650
diva Avatar asked Sep 25 '22 16:09

diva


1 Answers

Modern browsers support the File and Directory Entries API which allows handling of directories (folders). At the time of writing, this works in Chrome, Firefox, Edge and Safari TP (no old IE support).

You have at least two ways to implement this (brownie points for doing both for best UX!).

Method 1: Using file input

Give the standard input element the power to handle directories via the webkitdirectory attribute:

<input
    #folderInput
    type="file"
    (change)="filesPicked(folderInput.files)"
    webkitDirectory
>

Note: the above HTML snippet assumes Angular 2+, but you can easily do the same thing in Angular 1

folderInput.files will be a flat list of all files within the folder, no need to recursively walk the tree or anything like that. Just iterate through the files in a simple loop like this:

function filesPicked(files) {
    for (let i = 0; i < files.length; i++) {
        const file = files[i];
        const path = file.webkitRelativePath.split('/');
        // upload file using path
        ...
    }
}

The property webkitRelativePath, as the name suggests, contains a path of the file relative to the ancestor directory the user selected.

Method 2: Using drag and drop

Another part of the same File and Directory Entries API is DataTransferItem.webkitGetAsEntry() which returns a FileSystemFileEntry or FileSystemDirectoryEntry. If it's a directlry, you can read it via a FileSystemDirectoryReader retrieved by calling FileSystemDirectoryEntry.createReader(). Here's a brief example of handling the drop event:

function drop(event) {
    const items = event.dataTransfer.items;
    for (let i = 0; i < items.length; i++) {
        const item = items[i];
        if (item.kind === 'file') {
            const entry = item.webkitGetAsEntry();
            if (entry.isFile) {
                 return new Promise((resolve, reject) => {
                    entry.file( 
                        file => {
                            resolve(file);
                        },
                        err => {
                            reject(err);
                        }
                    );
                });
            } else if (entry.isDirectory) {
                const directoryReader = entry.createReader();
                return new Promise((resolve, reject) => {
                    directoryReader.readEntries(
                        entries => {
                            resolve(entries);
                        },
                        err => {
                            reject(err);
                        }
                    );
                });
            }
        }
    }
}

My coworker wrote a short article explaining the approach in more detail (disclaimer: I work for that company).

Here's a fully working Plunkr demo from the article: https://plnkr.co/edit/rFC9Ln

like image 63
Dmitry Pashkevich Avatar answered Oct 03 '22 00:10

Dmitry Pashkevich