nodejs fs模块读取文件的路径问题

前言

相信绝大多数的前端和我一样都习惯用相对路径,因为在写前端代码的时候基本上都是用相对路径,而很少使用绝对路径,使用相对路径在当使用nodejs的fs模块读取文件时就有可能会给自己挖下这么一个坑(经典的nodejs的路径问题),问题如下:

问题

现在有一个demo,文件目录结构如下图:
目录结构
server.js的代码为:

let http = require('http');
let fs = require('fs');
let path = require('path');
const PORT = 3000;

// web页面的根路径
// 注意:现在这里是相对路径
let PUBLIC_PATH = '../public';

http.createServer((req, res) => {
    if (req.url === '/favicon.ico') {
        res.end();
        return;
    }
    let _path = '';
    console.log(`请求路径为:${req.url}`);

    if (req.url === '/') {
        _path = PUBLIC_PATH + '/home.html';
    }else {
        _path = PUBLIC_PATH + req.url;
    }
    sendFile(res, _path);
}).listen(PORT, () => {
    console.log('Server listening on port 3000.');
});

function sendFile(res, path) {
    fs.exists(path, (exist) => {
        if (exist) {
            fs.readFile(path, (err, file) => {
                if (err) {
                    send404(res);
                } else {
                    let mime = '';
                    if (path.indexOf('.html')) {
                        mime = 'text/html';
                    }else if (path.indexOf('.js')) {
                        mime = 'application/javascript';
                    }
                    res.writeHead(200, {'Content-type': `${mime};chartset=utf-8`});
                    console.log('status : 200');
                    res.end(file);
                }
            });
        } else {
            send404(res);
        }
    });
}

function send404(res) {
    res.writeHead(404, {'Content-type': 'text/plain'});
    console.log('status : 404');
    res.end('404');
}

注意这里是以相对路径去读写静态资源:

// web页面的根路径
// 注意:现在这里是相对路径
let PUBLIC_PATH = '../public';

然后以以下命令启动server.js并访问localhost:3000,打印结果为:
result
可以看到,正确访问到资源。
但是当以以下命令启动server.js并访问localhost:3000,打印结果为:
result
可以看到,无法访问到资源。
然后改变:

// web页面的根路径
// 注意:现在这里是相对路径
let PUBLIC_PATH = './public';

然后以以下命令启动server.js并访问localhost:3000,打印结果为:
result3
可以看到,正确访问到资源。
显而易见,fs模块读取文件的相对路径是以启动server.js的位置为基准的,而不是以server.js文件的位置
这就是这篇文章所要讲述的问题。

解决

很显然,启动脚本的方式可以有多种,所以nodejs官方推荐在使用fs模块读取文件时使用绝对路径,而不是相对路径。
改变:

// web页面的根路径
// 注意:现在改为绝对路径
let PUBLIC_PATH = path.resolve(__dirname, '../public');

经测试,无论在那个位置启动server.js都可以访问到静态资源。

路径

仍然以上面demo的目录结构(环境:window10;node v8.4.0),总结一些nodejs的常用路径:

    //获取node.exe的绝对路径
    console.log(process.execPath);//D:\nodejs\node.exe

    //存放当前文件(即server.js)文件夹的绝对路径
    console.log(__dirname);//D:\nodeTest\node_path\lib

    //当前文件(即server.js)的绝对路径
    console.log(__filename);//D:\nodeTest\node_path\lib\server.js

    //从所传入的文件路径(相对或绝对)中获取存放传入文件的文件夹的相对或绝对路径 
    //(例如 传入 public/home.html 则返回的是public)
    console.log(path.dirname(__filename));//D:\nodeTest\node_path\lib

    //执行当前脚本(即server.js)的位置 (例如 在根目录下执行 node ./xxx/xxx/a.js 则返回的是根目录地址 )
    console.log(process.cwd());//D:\nodeTest\node_path\lib

    //'a/b/c'和'../src' 组合而成的绝对路径 文件或文件夹都行
    //例如 console.log(path.resolve('a/b/c', '../src'));//D:\nodeTest\node_path\lib\a\b\src
    console.log(path.resolve(__dirname, '../public'));//D:\nodeTest\node_path\public

    //'a/b/c'和'../src'组成的相对路径
    //console.log(path.join('a/b/c', '../src'));//a\b\src
    console.log(path.join(__dirname, '../public'));//D:\nodeTest\node_path\public

    //相当于path.resolve(__dirname, '../public/home.html')或path.join(__dirname, '../public/home.html')
    //但传入的必须是文件路径,而不是文件夹路径,而且当文件不存在时会抛出异常
    console.log(require.resolve('../public/home.html'));//D:\nodeTest\node_path\public\home.html
  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值