Paul Kruger
Paul Kruger

Reputation: 2304

Nodejs save JSON file

  1. Say I have this <input type="file" id="theFile">

  2. I access the selected file with with myVar = document.getElementById('theFile').value

  3. The output is console.log(myVar); // C:\fakepath\xxx.txt

Then I do a simple POST, there are many ways to do a POST but one basic JavaScript way is:

var http = new XMLHttpRequest();
http.onreadystatechange = function() { 
http.open("POST", "http://localhost:port/upload-test");
http.setRequestHeader('Content-type', 'application/json');
var body = {
    file: document.getElementById('theFile').value
}
http.send(JSON.stringify(body));

Then in my Nodejs Express service I do this:

app.post('/upload-test', (request, response) => {
    console.log(request.body); // { file: 'C:\\fakepath\\xxx.txt' }
});

Now how do I save that file to the pc the service is running on?

I know of other solutions like https://www.w3schools.com/nodejs/nodejs_uploadfiles.asp but this requires the user to use a <form> which is not what I want. I want to upload a file using a basic POST and JSON approach.

Upvotes: 1

Views: 1171

Answers (3)

Subha
Subha

Reputation: 31

You can use Multer module for file upload

const multer = require('multer');

Now set destinatoin folder to save the upladed files

const upload = multer({ dest: './uploads/' });

finally use upload.single() for single file upload or upload.array() for multiple file uploads

app.post('/upload-test',upload.single('myFile'),(request, response) => {
    console.log(request.body);
});

Upvotes: 0

Chris Adams
Chris Adams

Reputation: 1454

Client Side Firstly, you need to 'read' the file contents into a variable. You cannot upload a file directly as mentioned elsewhere on here.

I'm not sure what you're using client-side. E.g. React, Angular or plain Javascript. So, here's a link to another article on SO about how to select a client-side file and read its content into a var. Read Client-Side file

Once you have the file content in a var, you can 'post' that. E.g.

// Build the Headers object.
let headers = new Headers();
headers.append("Content-Type","application/json");

// Build the body object.
let body = {
    fileName: varContainingFileName,
    fileContent: varContianingContentsOfFile
};

// Build the request
const response = await fetch(URL, {method: 'POST',
                                    headers:headers, 
                                    body:JSON.stringify(body)});

// See what we get back from the service.  Note, for the await to work,
// Needs to be wrapped in async method.
console.log(response);

Server-Side I'm assuming you have set up your route for the API, so straight in....

const fs = require('fs');

uploadFile(req, res) {

    const requestBody = JSON.parse(req.body);

    log.info("Received File Upload request.  File " + requestBody.fileName);

    // If one doesn't exist, create a folder for the file
    fs.existsSync("./SomeFolder/") || fs.mkdirSync("./SomeFolder/");

    // Using method.then(otherMethod) with promises.
    writeSourceDataToFile (requestBody.fileName,
                            "./SomeFolder/",
                            requestBody.fileContent)
      .then(v => finalMethod(v, requestBody.fileName, "./SomeFolder/", res))
      .catch(err => returnError(res, err) );

}

function writeSourceDataToFile (fileName, path, content) {

    return new Promise((resolve, reject) => {

        // User fs write stream to stream the file content var to file.
        let writeSource = fs.createWriteStream(path + fileName)
            .on('end', function () {
                log.info("File wrote to disk - End event");
                resolve (true);
            })
           .on('finish', function () {
               log.info("File wrote to disk - Finish event");
               resolve (true);
            })
           .on('error', function (err) {
               log.info('Error whilst writing file - ' + fileName);
               reject (err);
           });

        writeSource.write(content);

        writeSource.end();

    });
}

function finalMethod(v, fileName, path, res) {

    // Final method just wraps things up and sends some message back to 
    // client.

    log.info(fileName + " File Upload Process Completed.");
    res.write("File Upload Process Completed.\n");

    res.status(200).end();

}

// Something went wrong, log it and tell the client.
function returnError(res, err) {
  log.error(err);
  res.status(500).send(err);
}

Upvotes: 0

Jairo Malanay
Jairo Malanay

Reputation: 1347

The content-type of the request should be multipart/form-data, cos you are uploading the file. you can use multerjs for nodejs upload

var express = require('express')
var multer  = require('multer')
var upload = multer({ dest: 'uploads/' })

var app = express()

app.post('/upload-test', upload.single('avatar'), function (req, res, next) {
  // req.file is the `avatar` file
  // req.body will hold the text fields, if there were any
})

Upvotes: 1

Related Questions