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
CodePudding user response:
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);