2016-07-11 90 views
0

我有一個儀表板可以生成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,因此它應該跟隨創建文件路徑。

如果你知道關於node和文件系統模塊的任何內容,並且覺得自己幫助我,即使它只是指向我一些更多教程的方向,那也是驚人的......任何事情都會很棒!

-

'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; 
+0

當你發送一個新的文件,第一次調用創建文件夾,但未來的呼叫失敗,正如你所說的'updateFile'當你'fs.mkdir '與EEXIST失敗。但這意味着文件夾存在,而不是文件。 –

回答

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參數,因爲你可能會暴露你的文件系統無意覆蓋。

+0

完美...我用這個,但增加了將wirteFile放入readFile(if)中,因爲當我需要在文件已經存在時追加json對象 – iamleeadamson

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); 
      }); 
     } 

    }); 

    }); 
}); 
相關問題