Created
February 26, 2017 22:03
-
-
Save meziantou/935050b4fd415a9e45add91c68ca0c95 to your computer and use it in GitHub Desktop.
FileUpload (drag and drop files and directories, paste)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
improveFileUpload(); | |
function improveFileUpload() { | |
const input = document.getElementById("FileUpload"); | |
if (!input) { | |
console.warn("input not found."); | |
return; | |
} | |
if (!(input instanceof HTMLInputElement)) { | |
console.warn("element is not an input element."); | |
return; | |
} | |
const dropZone = input; | |
if (dropZone) { | |
const hoverClassName = "hover"; | |
// TODO replace with addEventListener | |
dropZone.addEventListener("dragenter", function (e) { | |
e.preventDefault(); | |
dropZone.classList.add(hoverClassName); | |
}); | |
dropZone.addEventListener("dragover", function (e) { | |
e.preventDefault(); | |
dropZone.classList.add(hoverClassName); | |
}); | |
dropZone.addEventListener("dragleave", function (e) { | |
e.preventDefault(); | |
dropZone.classList.remove(hoverClassName); | |
}); | |
dropZone.addEventListener("drop", async function (e) { | |
e.preventDefault(); | |
dropZone.classList.remove(hoverClassName); | |
const files = await getFilesAsync(e.dataTransfer); | |
console.log(files); | |
}); | |
} | |
dropZone.addEventListener("paste", async function (e) { | |
e.preventDefault(); | |
const files = await getFilesAsync(e.clipboardData); | |
console.log(files); | |
}); | |
} | |
async function getFilesAsync(dataTransfer: DataTransfer) { | |
const files: File[] = []; | |
for (let i = 0; i < dataTransfer.items.length; i++) { | |
const item = dataTransfer.items[i]; | |
if (item.kind === "file") { | |
if (typeof item.webkitGetAsEntry === "function") { | |
const entry = item.webkitGetAsEntry(); | |
const entryContent = await readEntryContentAsync(entry); | |
files.push(...entryContent); | |
continue; | |
} | |
const file = item.getAsFile(); | |
if (file) { | |
files.push(file); | |
} | |
} | |
} | |
return files; | |
} | |
function readEntryContentAsync(entry: FileSystemEntry) { | |
return new Promise<File[]>((resolve, reject) => { | |
let reading = 0; | |
const contents: File[] = []; | |
readEntry(entry); | |
function readEntry(entry: FileSystemEntry) { | |
if (isFile(entry)) { | |
reading++; | |
entry.file(file => { | |
reading--; | |
contents.push(file); | |
if (reading === 0) { | |
resolve(contents); | |
} | |
}); | |
} else if (isDirectory(entry)) { | |
readReaderContent(entry.createReader()); | |
} | |
} | |
function readReaderContent(reader: FileSystemDirectoryReader) { | |
reading++; | |
reader.readEntries(function (entries) { | |
reading--; | |
for (const entry of entries) { | |
readEntry(entry); | |
} | |
if (reading === 0) { | |
resolve(contents); | |
} | |
}); | |
} | |
}); | |
} | |
function isDirectory(entry: FileSystemEntry): entry is FileSystemDirectoryEntry { | |
return entry.isDirectory; | |
} | |
function isFile(entry: FileSystemEntry): entry is FileSystemFileEntry { | |
return entry.isFile; | |
} | |
interface FileSystemEntry { | |
fullPath: string; | |
isFile: boolean; | |
isDirectory: boolean; | |
name: string; | |
getMetadata(successCallback: (metadata: Metadata) => void, errorCallback?: (error: FileError) => void): void; | |
} | |
interface FileSystemFileEntry extends FileSystemEntry { | |
file(successCallback: (file: File) => void, errorCallback?: (error: FileError) => void): void; | |
} | |
interface FileSystemDirectoryEntry extends FileSystemEntry { | |
createReader(): FileSystemDirectoryReader; | |
getDirectory(): FileSystemDirectoryEntry; | |
getFile(): FileSystemFileEntry; | |
} | |
interface DataTransferItem { | |
webkitGetAsEntry?(): FileSystemEntry; | |
} | |
interface FileSystemDirectoryReader { | |
readEntries(successCallback: (entries: FileSystemEntry[]) => void, errorCallback?: (error: FileError) => void): void; | |
} | |
interface Metadata { | |
modificationTime: Date; | |
size: number; | |
} | |
interface FileError extends Error { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment