使用JSZip解压缩文件时会给出一个文件夹和文件列表。例如,当我运行
files.forEach((relativePath, file) => {
console.log(relativePath);
});
我明白了:
three-dxf-master/
three-dxf-master/.DS_Store
three-dxf-master/.gitignore
three-dxf-master/LICENSE
three-dxf-master/README.md
three-dxf-master/bower.json
three-dxf-master/bower_components/
其中一些是目录,一些是文件。
我可以通过检查file.dir
来判断哪些是目录。
我想将其拆分为分层数据结构。我想把它分开:
{
"three-dxf-master": [
".DS_Store",
".gitignore",
"LICENSE",
"README.md",
"bower.json",
{
"bower_components": [
".DS_Store",
{
"dxf-parser": [...]
}
]
}
]
}
这样我就可以将它发送到Vue并在一个漂亮的文件查看器中进行格式化。我查看了文档,但我没有看到为文件创建层次结构数据结构的简单方法。我开始通过在分割后抓取文件路径中的最后一个来研究这个问题。
答案 0 :(得分:4)
这是一个示例代码,它也处理root文件。
请参阅以下代码摘要解释。
var paths = [
"three-dxf-master/",
"three-dxf-master/.DS_Store",
"three-dxf-master/.gitignore",
"three-dxf-master/LICENSE",
"three-dxf-master/README.md",
"three-dxf-master/bower.json",
"three-dxf-master/bower_components/",
"three-dxf-master/bower_components/.DS_Store",
"three-dxf-master/bower_components/dxf-parser/",
"three-dxf-master/bower_components/dxf-parser/foo",
"three-dxf-master/bower_components/dxf-parser/bar",
"three-dxf-master/dummy_folder/",
"three-dxf-master/dummy_folder/foo",
"three-dxf-master/dummy_folder/hello/",
"three-dxf-master/dummy_folder/hello/hello",
]
// Extract a filename from a path
function getFilename(path) {
return path.split("/").filter(function(value) {
return value && value.length;
}).reverse()[0];
}
// Find sub paths
function findSubPaths(path) {
// slashes need to be escaped when part of a regexp
var rePath = path.replace("/", "\\/");
var re = new RegExp("^" + rePath + "[^\\/]*\\/?$");
return paths.filter(function(i) {
return i !== path && re.test(i);
});
}
// Build tree recursively
function buildTree(path) {
path = path || "";
var nodeList = [];
findSubPaths(path).forEach(function(subPath) {
var nodeName = getFilename(subPath);
if (/\/$/.test(subPath)) {
var node = {};
node[nodeName] = buildTree(subPath);
nodeList.push(node);
} else {
nodeList.push(nodeName);
}
});
return nodeList;
}
// Build tree from root
var tree = buildTree();
// By default, tree is an array
// If it contains only one element which is an object,
// return this object instead to match OP request
if (tree.length == 1 && (typeof tree[0] === 'object')) {
tree = tree[0];
}
// Serialize tree for debug purposes
console.log(JSON.stringify(tree, null, 2));
<强>解释强>
function getFilename(path) {
return path.split("/").filter(function(value) {
return value && value.length;
} ).reverse()
[0];
}
要获取文件名,路径将被
/
拆分。/ path / to / dir / =&gt;
['path', 'to', 'dir', '']
/ path / to / file =&gt;
['path', 'to', 'file']
仅保留具有长度的值,此句柄目录路径。
文件名是我们数组的最后一个值,为此我们很简单 反转数组并获取第一个元素。
function findSubPaths(path) {
// slashes need to be escaped when part of a regexp
var rePath = path.replace("/", "\\/");
var re = new RegExp("^" + rePath + "[^\\/]*\\/?$");
return paths.filter(function(i) {
return i !== path && re.test(i);
});
}
要查找路径的子路径,我们在路径列表中使用过滤器。
过滤器使用正则表达式(演示为available here)来测试路径是以父路径开始并以
/
(这是dir路径)结束还是结束line(这是一个文件路径)。如果测试路径不等于父路径并且与正则表达式匹配,则过滤器接受它。否则就被拒绝了。
function buildTree(path) {
path = path || "";
var nodeList = [];
findSubPaths(path).forEach(function(subPath) {
var nodeName = getFilename(subPath);
if(/\/$/.test(subPath)) {
var node = {};
node[nodeName] = buildTree(subPath);
nodeList.push(node);
}
else {
nodeList.push(nodeName);
}
});
return nodeList;
}
既然我们有从路径中提取文件名并查找子路径的方法,那么构建我们的树非常容易。 Tree是一个nodeList。
如果子路径以
/
结束,则它是一个目录,我们在将节点附加到nodeList之前递归调用buildTree
。否则我们只需将文件名添加到nodeList。
附加代码
if (tree.length == 1 && (typeof tree[0] === 'object')) {
tree = tree[0];
}
默认情况下,返回的树是一个数组。
要匹配OP请求,如果它只包含一个作为对象的元素,那么我们将返回此对象。
答案 1 :(得分:1)
您可以将行拆分为记录,然后将每个记录拆分为字段。处理时,确定字段是目录还是文件。如果是目录,请查看它是否是子目录,如果它不存在则创建它。然后进入它。
如果它是一个文件,只需按下当前目录即可。
OP中的格式不允许根目录中的文件,因此如果遇到一个文件,则会引发错误。要允许根目录中的文件,基础对象必须是一个数组(但它似乎是一个对象)。
以下内容还允许路径以任何顺序排列并且非顺序地创建,例如,它会接受:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
它不需要:
foobar/fum
希望评论足够。
foobar/
foobar/fum
&#13;
答案 2 :(得分:0)
<强>信息强>
在尝试此页面中的所有解决方案后,正在寻找实施,每个都有错误。
最后我找到了this
<强>解决方案强>
您需要在jszip路径输出中添加“/”以使用该算法,您可以使用forEach循环。
var paths = [
'/FolderA/FolderB/FolderC/Item1',
'/FolderA/FolderB/Item1',
'/FolderB/FolderD/FolderE/Item1',
'/FolderB/FolderD/FolderE/Item2',
'/FolderA/FolderF/Item1',
'/ItemInRoot'
];
function arrangeIntoTree(paths, cb) {
var tree = [];
// This example uses the underscore.js library.
_.each(paths, function(path) {
var pathParts = path.split('/');
pathParts.shift(); // Remove first blank element from the parts array.
var currentLevel = tree; // initialize currentLevel to root
_.each(pathParts, function(part) {
// check to see if the path already exists.
var existingPath = _.findWhere(currentLevel, {
name: part
});
if (existingPath) {
// The path to this item was already in the tree, so don't add it again.
// Set the current level to this path's children
currentLevel = existingPath.children;
} else {
var newPart = {
name: part,
children: [],
}
currentLevel.push(newPart);
currentLevel = newPart.children;
}
});
});
cb(tree);
}
arrangeIntoTree(paths, function(tree) {
console.log('tree: ', tree);
});
我还需要在交互式树中显示数据,我使用了angular-tree-control,它接受了确切的格式。