节点文件系统在发布路径上创建目录和文件

时间:2016-07-11 11:29:13

标签: javascript node.js express fs

我有一个生成JSON数据的仪表板并将其保存为.json文件。这最初是用PHP编写的,但由于各种原因,我们在节点中重写了应用程序。下面的代码获取后期数据,然后应检查该文件是否存在,如果它确实更新它,如果不存在则应该创建文件和目录。

然而,它似乎只是创建了第一个文件而我无法理解它为什么不创建后续文件,因为每个帖子都会调用一次这个帖子。

post方法看起来像这样

$.ajax({
    type : "POST",
    url : '/save/',
    dataType : 'json',
    data : {
    category : settings.category_id,
    name : settings.campaignId,
    json : JSON.stringify(settings)
    }
});

我已经调试过,当调用时,所有正确的文件路径都被传递,但它几乎就像文件没有被写入数据一样。

在使用node-inspector和nodemon进行调试期间,代码循环遍历所有请求的新文件名,并向我提供错误代码ENOENT,因此它应该遵循创建文件路径。

如果您对节点和文件系统模块一无所知,并且感觉像是帮助我那将是惊人的,即使它只是指向我更多教程的方向,......任何事情都会很棒!

-

'use strict'

const fs = require('fs');
const path = require('path');
const express = require('express');
const router = express.Router();

/* Save Data */
router.post('/', function(req, res) {

  if (!(req.body.json && req.body.name && req.body.category)) {
    res.sendStatus(400);
    return;
  }

  let dir = 'public/savedData/' + req.body.category;
  let filepath = dir + '/' + req.body.name + '.json';

  fs.access(filepath, function(error) {
    console.log(filepath);

    console.log(error.code);
    if (error) {
        if (error.code == 'ENOENT') {
            console.log(error.code);
            //debugger;
            // Create file since it doesn't exist
            createFile(req, res, filepath);

        } else {
            //debugger;
            console.log('access error:', error);
            res.sendStatus(500);
        }
    } else {
        //debugger;
        // Update file since it already exists
        updateFile(req, res, filepath);
    }
});
});

function createFile(req, res, filepath) {
try {
    let json = JSON.parse(req.body.json);
    let output = JSON.stringify([json], null, 4);

    fs.mkdir(path.dirname(filepath), function(error) {
        if (error) {
            if (error.code == 'EEXIST') {
                updateFile(req, res, filepath);
            } else {
                res.sendStatus(500);
                console.log('create file error :', error);
            }
        } else {
            fs.writeFile(filepath, output, function(error) {
                if (error) {
                    res.sendStatus(500);
                    console.log('write file error :', error);
                } else {
                    res.sendStatus(200);
                    console.log('Data successfully saved');
                }
            });
        }
    });
} catch (error) {
    res.sendStatus(500);
    console.log(error);
}
}

function updateFile(req, res, filepath) {

try {
    fs.readFile(filepath, 'utf-8', function(error, data) {
        if (error) {
            res.sendStatus(500);
            console.log('update error:', error);
        } else {
            try {
                let newJSON = JSON.parse(req.body.json);
                let jsonArray = JSON.parse(data);
                let output;

                jsonArray.push(newJSON);
                output = JSON.stringify(jsonArray, null, 4);

                fs.writeFile(filepath, output, function(error) {
                    if (error) {
                        res.sendStatus(500);
                        console.log(error);
                    } else {
                        res.sendStatus(200);
                        console.log('Data successfully saved');
                    }
                });
            } catch (error) {
                res.sendStatus(500);
                console.log(error);
            }
        }
    });
} catch (error) {
    res.sendStatus(500);
    console.log(error);
}
}

module.exports = router;

2 个答案:

答案 0 :(得分:1)

您应该尝试使用标记wx进行写入,而不是检查文件是否存在,这会创建一个文件但如果文件已经存在则会失败。这样你就不会受到竞争条件的影响。我还建议使用包mkdirp,如果目录已存在,则不会发出错误。

router.post('/', (req, res) => {
  if (!(req.body.json && req.body.name && req.body.category)) {
    res.sendStatus(400);
    return;
  }

  const dirpath  = `public/savedData/${req.body.category}`;
  const filepath = `${dirpath}/${req.body.name}.json`;

  mkdirp(dirpath, err => {
    if (err) {
      console.error('mkdirp failed', err);
      return res.sendStatus(500);
    }

    const output = JSON.stringify([JSON.parse(req.body.json)]);

    fs.writeFile(filepath, output, { flags: 'wx' }, err => {
      if (err) {
        console.error('writeFile failed', err);
        return res.sendStatus(500);
      }

      console.log('Data successfully saved');
      res.sendStatus(200);
    });
  );
});

确保您清理req.body.namereq.body.category参数,因为您可能会将文件系统暴露给无意的覆盖。

答案 1 :(得分:0)

感谢@Iso这是我的解决方案

router.post('/', (req, res) => {
  if (!(req.body.json && req.body.name && req.body.category)) {
  res.sendStatus(400);
  return;
}

const dirpath  = 'public/savedData/' + req.body.category;
const filepath = dirpath + '/' + req.body.name + '.json';

mkdirp(dirpath, err => {
  if (err) {
    console.error('mkdirp failed', err);
    return res.sendStatus(500);
  }

const output = JSON.stringify([
        JSON.parse(req.body.json)
    ]);
    fs.readFile(filepath, 'utf-8', function(error, data) {
        if(error) {
            fs.writeFile(filepath, output, err => {
                if (err) {
                    console.error('writeFile failed', err);
                    return res.sendStatus(500);
                }

                console.log('Data successfully saved');
                res.sendStatus(200);
            });
        } else {
            let newJSON = JSON.parse(req.body.json);
            let jsonArray = JSON.parse(data);
            let output;

            jsonArray.push(newJSON);
            output = JSON.stringify(jsonArray, null, 4);

            fs.writeFile(filepath, output, err => {
                if (err) {
                    console.error('writeFile failed', err);
                    return res.sendStatus(500);
                }

                console.log('Data successfully saved');
                res.sendStatus(200);
            });
        }

    });

  });
});