如何递归遍历目录,通过 node.js 中的套接字发送所有文件名?

Posted

技术标签:

【中文标题】如何递归遍历目录,通过 node.js 中的套接字发送所有文件名?【英文标题】:How can I recursively walk a directory, sending all file names over a socket in node.js? 【发布时间】:2013-09-25 09:54:59 【问题描述】:

我正在尝试使节点服务器能够通过 Web 套接字将目录中找到的所有文件名(递归)发送到客户端。这里的想法是目录非常大,我想在读取整个目录之前开始在客户端获取结果。

我想应该这样做:

服务器端:

var express = require('express'),
  app = express(),
  server = require('http').createServer(app),
  io = require('socket.io').listen(server),
  fs = require('graceful-fs'),
  rootDirectory = "/some/absolute/path";
  port = 3000,
  recursivelyReadDirectory = function (rootDirectory) 
    // TODO
  ,
  sync = io
    .of('/sync')
    .on('connection', function (socket) 
      recursivelyReadDirectory(rootDirectory).on('chunk', function (filename) 
       socket.emit('filename', filename);
      );
    );
server.listen(port);

客户端:

var socket = io.connect('http://localhost:3000/sync');
socket.on('filename', function (filename) 
  console.log(filename);
);

如果我在服务器上的 /some/absolue/path 中有以下内容:

.
|-- a
|   `-- c.txt
`-- b.txt

我希望客户端脚本能够记录

c.txt
b.txt

b.txt
c.txt

【问题讨论】:

看看this question,好像覆盖了目录遍历部分 【参考方案1】:

我创建了一个小的工作示例:

app.js

var express = require('express'),
    app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server),
    fs = require('fs'),
    rootDirectory = "c:/tmp",
    port = 3000,
    recursivelyReadDirectory = function (rootDirectory) 
        // TODO
    ;

app.use(express.static(__dirname + '/public'));

var walk = function (dir, action, done) 

    // this flag will indicate if an error occured (in this case we don't want to go on walking the tree)
    var dead = false;

    // this flag will store the number of pending async operations
    var pending = 0;

    var fail = function (err) 
        if (!dead) 
            dead = true;
            done(err);
        
    ;

    var checkSuccess = function () 
        if (!dead && pending == 0) 
            done();
        
    ;

    var performAction = function (file, stat) 
        if (!dead) 
            try 
                action(file, stat);
            
            catch (error) 
                fail(error);
            
        
    ;

    // this function will recursively explore one directory in the context defined by the variables above
    var dive = function (dir) 
        pending++; // async operation starting after this line
        fs.readdir(dir, function (err, list) 
            if (!dead)  // if we are already dead, we don't do anything
                if (err) 
                    fail(err); // if an error occured, let's fail
                
                else  // iterate over the files
                    list.forEach(function (file) 
                        if (!dead)  // if we are already dead, we don't do anything
                            var path = dir + "/" + file;
                            pending++; // async operation starting after this line
                            fs.stat(path, function (err, stat) 
                                if (!dead)  // if we are already dead, we don't do anything
                                    if (err) 
                                        fail(err); // if an error occured, let's fail
                                    
                                    else 
                                        if (stat && stat.isDirectory()) 
                                            dive(path); // it's a directory, let's explore recursively
                                        
                                        else 
                                            performAction(path, stat); // it's not a directory, just perform the action
                                        
                                        pending--;
                                        checkSuccess(); // async operation complete
                                    
                                
                            );
                        
                    );
                    pending--;
                    checkSuccess(); // async operation complete
                
            
        );
    ;

    // start exploration
    dive(dir);
;

io
    .on('connection', function (socket) 
        walk(rootDirectory, function (path, stat) 
            console.log(path);
            socket.emit('filename', path);
        , function (err) 
            if (err) 
                socket.emit('error', 'Something went wrong');
             else 
                socket.emit('done');
            
        );
    );
server.listen(port);

index.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
    var socket = io.connect('http://localhost');
    socket.on('filename', function (data) 
        console.log(data);
    );
</script>
</body>
</html>

【讨论】:

以上是关于如何递归遍历目录,通过 node.js 中的套接字发送所有文件名?的主要内容,如果未能解决你的问题,请参考以下文章

js如何遍历本地目录的文件

我如何连接到 Node.js 中的星号

javascript [node.js 8+]递归获取目录中的所有文件

为啥 Node.js 中的某些 TCP 套接字比大多数其他套接字需要更多的时间来连接?

如何将数据从 Android 中的数据报套接字发送到 Node js 服务器?

无法通过递归调用node.js中的函数从promises获得响应