-1

I am trying to write a request from an API endpoint to a file with node packages express and file-system. However, when I run the writeFile function, neither a folder or txt file is written to the file system.

I have checked the folder permissions and they seem to be set correctly. Also, the error callbacks seem to return null in the console log.

Server code

app.use((req, res, next) => {       // Enable Cross-Origin Resource Sharing (CORS)
  res.header("Access-Control-Allow-Origin", "*")
  res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT")
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, content-type, Accept, Authorization, x-api-key")
  next()
})


app.post("/node/api/mssql/post-order-header", (req, res, next) => {
  if(valid) write.orderHeader(req, res)
})

Module code

let fs = require("fs")

...

exports.orderHeader = (req, res, next) => {
  fs.writeFile('_log/receipts/test.txt', JSON.stringify(req.body), (err) => {
    if (err) throw err;
    console.log('The file has been saved!');
  })
})

Error

C:\...\fs\write_order.js:17
if (err) throw err;
Error: ENOENT: no such file or directory, open 'C:...\test-folder\test.txt'

Is this possible to do with Node? (Want to create a new file each time)

Matthew
  • 1,461
  • 3
  • 23
  • 49
  • try changing you parameters for `writeFile` to: `'./test-folder/test.txt', JSON.stringify(req.body), 'utf8', err => console.log(err))` – m_callens Jan 09 '18 at 20:08
  • Why not just use the native `fs` module? Also, fwiw if you have your module in the node_modules directory, you should just have to do `const fs = require('file-system')` not providing the path. – Paul Jan 09 '18 at 20:09
  • This should be `let fs = require('file-system')`, but I don't think that will fix your issue – Explosion Pills Jan 09 '18 at 20:09
  • 3
    Possible duplicate of [Writing files in Node.js](https://stackoverflow.com/questions/2496710/writing-files-in-node-js) – malifa Jan 09 '18 at 20:10
  • @m_callens OK. Tried this. Still nothing is being written. – Matthew Jan 09 '18 at 20:12
  • @Paul It seemed like the fs module was deprecated or deleted in the npm registry. https://www.npmjs.com/package/fs – Matthew Jan 09 '18 at 20:13
  • @lexith Read through that post, but it's a different module. – Matthew Jan 09 '18 at 20:13
  • because it's part of the core... – malifa Jan 09 '18 at 20:14
  • @Matthew I'm talking about the [native fs module in node.js](https://nodejs.org/dist/latest-v8.x/docs/api/fs.html) – Paul Jan 09 '18 at 20:14
  • @Matthew your folder structure isn't setup right, then. Do you have a package.json at the root of your project? – Paul Jan 09 '18 at 20:15
  • @Paul Fixed that part based on your rec. – Matthew Jan 09 '18 at 20:19
  • OK. Thanks for the recommendations. It's still not working. Is there any way to error log more verbosely? – Matthew Jan 09 '18 at 20:22

1 Answers1

3

You have to import fs module like this:

const fs = require('fs');

fs.mkdir is asynchronous you need to call fs.writeFile inside the callback function, And use JSON.stringify(res.body) object before writing the file. and one final thing, it seems that you are exporting a middleware that's why you should complete the middleware signature by adding the next method too:

const fs = require('fs');

exports.orderHeader = (req, res, next) => {

    console.log(req.body)  // properly logs body

    fs.mkdir('test-folder', {mode: '777'}, (err) => {
        if (err) return next(err);

        fs.writeFile('test-folder/test.txt', JSON.stringify(req.body), (err) => {
            if (err) return next(err);

            next();
        })

    })
    
}
YouneL
  • 8,152
  • 2
  • 28
  • 50
  • OK. What does ```next``` do? – Matthew Jan 09 '18 at 20:21
  • Also, this did not work. It there any way to error check the permissions? – Matthew Jan 09 '18 at 20:22
  • It calls the next middleware – YouneL Jan 09 '18 at 20:22
  • how did you call this function ? – YouneL Jan 09 '18 at 20:26
  • No I want you to show me the code of calling `orderHeader` function – YouneL Jan 09 '18 at 20:29
  • You have to pass the `next` function from the middleware into your orderHeader function. – Paul Jan 09 '18 at 20:38
  • @Paul Not sure what you mean... I updated the question. – Matthew Jan 09 '18 at 20:40
  • Your code is `app.post("/node/api/mssql/post-order-header", (req, res) => { if(valid) write.orderHeader(req, res) })`. You do not have a 'next' parameter passing from the middleware into the orderHeader function. Therefore next is undefined. – Paul Jan 09 '18 at 20:45
  • @Paul OK. Did that, updated question. Still same error: ```next is not a function ... at FSReqWrap.oncomplete```. – Matthew Jan 09 '18 at 20:48
  • @Matthew Please don't edit someone's answer like you are trying to do. You are changing what the answer's code actually does and modifying it while asking what certain facets of it actually do. – zero298 Jan 09 '18 at 21:00
  • @zero298 Like I said above, I clicked the wrong button. I edited it back to the original. – Matthew Jan 09 '18 at 21:01
  • @Matthew Have you created `_log/receipts/` directories on the main folder of express app ? – YouneL Jan 10 '18 at 11:38
  • @YouneL the ```fs``` module within node was directed at the root of the web app that was sending the data over to the express app. I created an answer that addressed this yesterday, but someone seems to have deleted it. – Matthew Jan 10 '18 at 13:51
  • @YouneL In my case, to direct back to the root of the express app it needs to be typed explicitly from ```./```. For example, ```./../express_root_folder/_log/receipts```. Since the web app and the express app share the same root. – Matthew Jan 10 '18 at 13:53
  • I would mark this answer as correct, but the details are actually more nuanced than the feedback posted here. Negative reputation has been given for cases not covered in the related post... – Matthew Jan 10 '18 at 13:54
  • Also, I am only able to get ```next()``` working when embedded in the ```server.js``` code, which returns ```Cannot POST /url/string/etc```, although the files are written. – Matthew Jan 10 '18 at 14:02
  • `next` param is optional when your middleware should render response to the client, in other word you have to terminate the request/response cycle by using one response method from this [link](https://expressjs.com/en/guide/routing.html#response-methods), or call the next middleware `next()` or you call [error handler middleware](https://expressjs.com/en/guide/error-handling.html) by `next(err)` – YouneL Jan 10 '18 at 14:18
  • @YouneL So, I would like to write two files out, ```fs.writeFile(...)fs.writeFile(...)``` consecutively. Putting ```res.send(res)``` at the end outside the file write file requests returned ```UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON```, and I am not sure how to handle this due to the asynchronicity. – Matthew Jan 10 '18 at 14:30
  • @YouneL Can I send back two JSON responses? One for each file write? – Matthew Jan 10 '18 at 14:31