<!DOCTYPE html>
<html>
<head>
<title>Angular 2 QuickStart</title>
<!-- 1. Load libraries -->
<script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/angular2.dev.js"></script>
<!-- 2. Configure SystemJS -->
<script>
System.config({
transpiler: 'typescript',
typescriptOptions: { emitDecoratorMetadata: true },
packages: {'src': {defaultExtension: 'ts'}}
});
</script>
<!-- 3. Bootstrap -->
<script>
System.import('angular2/platform/browser').then(function(ng){
System.import('src/folder_upload').then(function(src) {
ng.bootstrap(src.FolderUpload);
});
});
</script>
</head>
<!-- 4. Display the application -->
<body>
<folder-upload>Loading...</folder-upload>
</body>
</html>
import {ChangeDetectorRef, Component} from 'angular2/core';
@Component({
selector: 'folder-upload',
templateUrl: 'src/folder_upload.html'
})
export class FolderUpload {
canDropFolder = typeof DataTransferItem.prototype.webkitGetAsEntry === 'function';
uploadPaths = [];
constructor(private cdr: ChangeDetectorRef) {}
dragenter(event) {
// indicates valid drop data
// false allows drop
return Array.prototype.every.call(
event.dataTransfer.items,
item => item.kind !== 'file'
);
}
dragover(event) {
// indicates valid drop data
// false allows drop
return Array.prototype.every.call(
event.dataTransfer.items,
item => item.kind !== 'file'
);
}
drop(event) {
const entries = Array.from(event.dataTransfer.items)
.filter(item => item.kind === 'file')
.map(item => item.webkitGetAsEntry());
this.buildTree(entries, '').then(tree => {
this.uploadPaths = [];
this.upload(tree, '');
this.cdr.markForCheck();
});
// indicates valid drop data
// false allows drop
return false;
}
filesPicked(files) {
console.log(files);
this.uploadPaths = [];
Array.prototype.forEach.call(files, file => {
this.uploadPaths.push(file.webkitRelativePath);
});
}
private parseFileEntry(fileEntry) {
return new Promise((resolve, reject) => {
fileEntry.file(
file => {
resolve(file);
},
err => {
reject(err);
}
);
});
}
private parseDirectoryEntry(directoryEntry) {
const directoryReader = directoryEntry.createReader();
return new Promise((resolve, reject) => {
directoryReader.readEntries(
entries => {
resolve(this.buildTree(entries, directoryEntry.name));
},
err => {
reject(err);
}
);
});
}
private buildTree(entries, name) {
const tree = {name, files: [], directories: []};
const promises = [];
entries.forEach(entry => {
if (entry.isFile) {
const promise = this.parseFileEntry(entry).then(file => {
tree.files.push(file);
});
promises.push(promise);
} else if (entry.isDirectory) {
const promise = this.parseDirectoryEntry(entry).then(directory => {
tree.directories.push(directory);
});
promises.push(promise);
});
return Promise.all(promises).then(() => tree);
}
private upload(tree, path) {
tree.files.forEach(file => {
this.uploadPaths.push(path + file.name);
});
tree.directories.forEach(directory => {
const newPath = path + directory.name + '/';
this.uploadPaths.push(newPath);
this.upload(directory, newPath);
});
}
}
<link rel="stylesheet" href="folder_upload.css">
<h1>Drop a folder to upload</h1>
<div
id="drop-area"
(dragenter)="dragenter($event)"
(dragover)="dragover($event)"
(drop)="drop($event)"
>
<span *ngIf="!canDropFolder">
Folder Drop Not Supported by Browser
</span>
</div>
<h1>Select a folder to upload</h1>
<div>
<input
#folderInput
type="file"
(change)="filesPicked(folderInput.files)"
webkitDirectory
>
</div>
<h1 *ngIf="uploadPaths.length > 0">Upload Data</h1>
<div *ngFor="#path of uploadPaths">{{path}}</div>
#drop-area {
border: 1px solid black;
width: 300px;
height: 100px;
}
#drop-area span {
color: red;
display: flex;
justify-content: center;
margin-top: 10px;
}
#text-output {
margin-top: 30px;
}