Everyone I'm trying to build something like google drive. I have finished the file upload functionality and I'm now working on the folder upload functionality for which I'm using the HTML file input (I'm using Next.js/React).
<input
type="file"
onChange={(e) => {
setFiles(e.target.files);
}}
webkitdirectory="true"
directory="true"
multiple
/>
after selecting a folder and uploading it I'm getting a File list
where I have the webkitRelativePath
property for each file like this --> "folder/childFolder/file".
now let's say I uploaded a folder which has many files and folders inside it add these are the webkitRelativePath
property for all the files
[ 'folder/childFile', 'folder/childFile2', 'folder/childFile3', 'folder/childFolder/childFile4', 'folder/childFolder/childFile5', 'folder/childFolder/grandchildFolder/childFile6', 'folder/childFolder/grandChildFolder/childFile7' ]
using this data I want to create a tree like structure like this -->
{
name: "folder",
children: [
{
name: "childFile",
children: [],
},
{
name: "childFile2",
children: [],
},
{
name: "childFile3",
children: [],
},
{
name: "childFolder",
children: [
{
name: "childFile4",
children: [],
},
{
name: "childFile5",
children: [],
},
{
name: "grandchildFolder",
children: [
{
name: "childFile6",
children: [],
},
{
name: "childFile7",
children: [],
},
],
},
],
},
],
}
I tried using loops and recursion but I was not able to make it work because everyfile is prefixed with the root folder and many more issues
Main part is addPath
function that can work both with empty object and with existing tree.
const tree = {};
const list = [
"folder/childFile",
"folder/childFile2",
"folder/childFile3",
"folder/childFolder/childFile4",
"folder/childFolder/childFile5",
"folder/childFolder/grandchildFolder/childFile6",
"folder/childFolder/grandChildFolder/childFile7"
];
const addPath = (path, tree) => {
// helper function to create child objects
const createChild = (name) => ({
name,
children: []
});
// split path to array of folders and files
const parts = path.split("/");
// create tree if empty
if (!tree.name) {
Object.assign(tree, createChild(parts[0]));
}
// check if root folder is correct
if (tree.name !== parts[0]) {
throw new Error(`Root folder is not "${tree.name}"`);
}
parts.shift();
// check and add other path parts
parts.reduce((current, p) => {
const child = current.children.find((child) => child.name === p);
if (child) {
return child;
}
const newChild = createChild(p);
current.children.push(newChild);
return newChild;
}, tree);
};
list.forEach((path) => addPath(path, tree));
console.log(tree);