【问题标题】:Unable to serve html file using 'http' module of Node.js无法使用 Node.js 的“http”模块提供 html 文件
【发布时间】:2018-07-02 03:38:50
【问题描述】:

我正在尝试在我的 http 服务器上提供一个 html 页面作为对“/”请求的响应。 但不知何故,它不起作用。

我的 index.html 是 -

<html>
<head>
    <title>File Explorer</title>
    <link rel='stylesheet' href='/stylesheets/style.css'/>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.min.css"/>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.js"></script>

</head>

<script>
    var fileExplorerApp = angular.module('explorerApp', []);
    fileExplorerApp.controller("MyController", function ($scope, $http) {
        var currentPath = '';
        $scope.reload = function (newPath, back) {
            if (back) {
                currentPath = newPath;
            } else {
                if (currentPath === '') {
                    currentPath = newPath;
                } else {
                    currentPath = currentPath + '/' + newPath;
                }
            }
            console.log('Newpath- ' + currentPath);
            $http.get('http://localhost:3000/list_dir?path=' + currentPath)
                .then(function (response) {
                    $scope.filesAndFolders = response.data;
                    $scope.currentPath = currentPath;
                }, function (error) {
                    console.log('Error in $http- ' + error);
                });    
        }

        $scope.back = function () {
            var prevPath = currentPath.substring(0, currentPath.lastIndexOf('/'));
            console.log('Path after substring- ' + prevPath);
            console.log('Prevpath when back clicked- ' + prevPath);
            $scope.reload(prevPath, true);

        }

        $scope.reload('F:/', false);
    });
</script>

<body ng-app="explorerApp" ng-controller="MyController">

<div class="ui container">
    <h1 id="currentPath">Current Directory- {{ currentPath }}</h1>
    <button ng-if="currentPath !== 'F:/'"
            ng-click="back()"
            class="ui left labeled icon button">
        <i class="left arrow icon"></i>
        Back
    </button>
    <div class="ui list">
        <a class="item"
           ng-repeat="item in filesAndFolders"
           ng-click="reload(item.name, false)"
           ng-href="{{item.type === 'file' ? '/get_file?path='+currentPath+'/'+item.name : ''}}">
            <i ng-if="item.type === 'folder'" class="folder icon"></i>
            <i ng-if="item.type === 'file'" class="file icon"></i>
            {{ item.name }}</a>
    </div>
</div>
</body>
</html>

通过 Angular,我正在访问另一个路由“/list_dir”并使用 Node.js(非 Express)的“http”模块处理请求。

if(parsedUrl.pathname === '/list_dir') {
            console.log('I\'m here');
            var file_path = parsedUrl.query['path'];
            list_dir.listDir(file_path, function (err, data) {
                if(err){
                    res.writeHeader(400, {'Content-Type':'text/json'});
                    res.write(err);
                } else {
                    console.log('in list_dir, no errors- response is- '+data);
                    res.writeHeader(200,{'Contenttype':'application/json'});
                    res.write(JSON.stringify(data));
                }
            });
            res.end();
            break;
        }

路由 '/list_dir' 然后访问另一个脚本中的函数,即 this-

module.exports = {
listDir: function (path, myCallback) {
    var resultObj = [];

    fs.readdir(path, function (err, data) {
        console.log('In listDir');
        if (err) {
            switch(err.code){
                case 'EACCES':
                    return myCallback({errno: err.errno, description: 'An attempt was made to access a file in a way forbidden by its file access permissions.'}, null);
                case 'ENOENT':
                    return myCallback({errno: err.errno, description: 'The specified path does not exist.'});
                case 'EPERM':
                    return myCallback({errno: err.errno, description: 'An attempt was made to perform an operation that requires elevated privileges.'})
                case 'ENOTDIR':
                    return myCallback({errno: err.errno, description: 'The specified path is not a directory.'})
            }
            return myCallback(err, null);
        }

        var itemsCompleted = 0;
        data.forEach(function (value) {
            fs.lstat(path + '/' + value, function (err, stats) {
                itemsCompleted++;
                if (err) {
                    console.log(err);
                } else {
                    if (stats.isFile()) {
                        resultObj.push({
                            type: 'file',
                            name: value,
                            size: stats['size']
                        });
                        //resultObj.push(value);
                        //console.log(resultObj + '\n');
                    } else if (stats.isDirectory()) {
                        resultObj.push({
                            type: 'folder',
                            name: value,
                            size: stats['size']
                        });
                    }
                }

                if (itemsCompleted >= data.length) {
                    //console.log(resultObj);
                    return myCallback(null, resultObj)
                }
            });
        });
    });
}

};

此函数返回给定路径内所有文件/文件夹的 json 对象,该对象将提供给 '/list_dir' 路由。但我没有从路线中得到正确的响应。

我希望这条路由使用 listDir 函数返回的相同 json 进行响应。我是 Node.js 的 http 模块的新手,可能我写错了标头,或者我以错误的方式使用数据。请帮忙。谢谢!

更新:

Chirags 的回答是正确的,现在 '/list_dir' 路由正在返回正确的 json 响应。但是,我仍然无法为我使用 AngularJS 使用此路由的 index.html 文件提供服务。

这就是我处理路线的方式-

if (parsedUrl.pathname === '/') {
    fs.readFile('./index.html', 'utf-8', function (err, fileResponse) {
        if (err) {
            console.log('Error');
            res.writeHeader(404, {
                "Content-Type": "text/html"
            });
            res.write('There was an error!');
        } else {
            console.log('No error');
            res.writeHeader(200, {
                "Content-Type": "text/html"
            });
            res.write(fileResponse);
        }
        res.end();
    });
}

这有什么问题?

【问题讨论】:

  • 您发布的代码乍一看还不错。您可以在设置服务器的位置发布整个文件并致电listen 等吗? PS:如果您的问题没有完全回答,请不要将答案标记为已接受。 (再见声誉;()..其他人不会看这个
  • console.log('No error'); 在您的回调中打印吗?我最好的猜测是您的路径匹配可能无法按预期工作,并且该代码块永远不会被执行
  • 是的。这正是它打印的内容-Server has been started at port 3000 The url is - / The pathname is - / 没有错误` 它没有去 '/list_dir' 路线从 listDir 函数中获取初始结果。我不知何故认为角度代码不起作用。
  • 它确实打印“无错误”
  • I somehow think the angular code isn't working 当您在浏览器中访问/ 时,您看到html 出现了吗?如果您的网页加载但您的 JS 没有运行,则问题可能出在 Angular 上。当您访问/ 时,您在浏览器中看到了什么?

标签: javascript angularjs node.js http response


【解决方案1】:

您过早地关闭了响应流。基本上,res.end() 在执行读取目录的异步函数并调用回调之前执行。试试:

if (parsedUrl.pathname === '/list_dir') {
    console.log('I\'m here');
    var file_path = parsedUrl.query['path'];
    list_dir.listDir(file_path, function (err, data) {
        if (err) {
            res.writeHeader(400, {
                'Content-Type': 'text/json'
            });
            res.write(err);
        } else {
            console.log('in list_dir, no errors- response is- ' + data);
            res.writeHeader(200, {
                'Contenttype': 'application/json'
            });
            res.write(JSON.stringify(data));
        }
        res.end();
    });
    break;
}

【讨论】:

  • 你能用相关代码更新你的问题吗?这通常是使用fs.readFile 并使用res.write 将文件写入回调中的响应的简单案例。如果您想流式传输响应,您甚至可以使用res.pipe(fileStream) 获取一个读取流并将其传送到您的响应对象
  • 不确定你的用例是什么,但使用 Express 或类似的东西可以通过抽象出一些更晦涩的 NodeJS 概念来轻松完成路由和发送文件等常见任务
  • 这绝对是真的,这就是我最初的做法。这实际上是给我的一个任务。我是通过 Express 完成的,但他们希望仅由“http”模块完成,而不是使用框架。这就是问题所在。
  • 为了让您对我的用例有一点了解,这是一个简单的任务,我必须制作一个 Web 应用程序来浏览我计算机上的文件。参考-this question
猜你喜欢
  • 2019-05-26
  • 2016-07-27
  • 1970-01-01
  • 1970-01-01
  • 2012-03-26
  • 2013-01-07
  • 1970-01-01
  • 2019-08-03
  • 1970-01-01
相关资源
最近更新 更多