What is the best way to include data with a file when making an HTTP POST request with AngularJS and ExpressJS?

Situation

I recently added file uploading functionality to my project. The front-end code was sourced from a popular tutorial on tutorialspoint. I am using the following service to send a POST request:

myApp.service('fileUpload', ['$http', function ($http) {
    this.uploadFileToUrl = function(file, uploadUrl){
        var fd = new FormData();
        fd.append('file', file);
        
        $http.post(uploadUrl, fd, {
             transformRequest: angular.identity,
             headers: {'Content-Type': undefined}
        })
        
        .success(function(){
        })
       
        .error(function(){
         });
        }
    }]);

The back-end uses multer in a typical way:

exports.postFile = function (req, res) {

    var storage = multer.diskStorage({ //multers disk storage settings
        destination: function (req, file, cb) {
            cb(null, '../documents/')
        },
        filename: function (req, file, cb) {
            cb(null, file.originalname)
        }
    });

    var upload = multer({ //multer settings
        storage: storage
    }).single('file');

    upload(req, res, function (err) {
        if (err) {
            res.json({error_code: 1, err_desc: err});
            return;
        }
        res.json({error_code: 0, err_desc: null});
    })

};

This setup is functioning correctly.

Question

Now, I am trying to figure out how to include additional data along with the file in the same POST request. For example, let's say I want to send a string like "additional info".

What I have attempted

In my service, I attempted to add the data like so:

...
var fd = new FormData();
fd.append('file', file);
fd.append('model', 'additional info');

$http.post(uploadUrl, fd, {...})

Although it appears to be sent successfully, I am unsure of how to access this extra data in the back-end. I looked through the req object but couldn't find it (no luck so far).

Answer №1

If you need to send both data (json format) and a file in one POST request, you can achieve this by adding them both to the form data object:

myApp.service('fileUpload', ['$http', function ($http) {
    this.uploadFileToUrl = function(file, uploadUrl){
        var fd = new FormData();
        fd.append('file', file);

        var info = {
            "text":"additional info"
        };
        fd.append('data', angular.toJson(info));

        $http.post(uploadUrl, fd, {
             transformRequest: angular.identity,
             headers: {'Content-Type': undefined}
        })

        .success(function(){
        })

        .error(function(){
        });
    }
}]);

On the server side, this information will be stored in req.body.data, making it accessible like so:

upload(req, res, function (err) {
    if (err) {
        res.json({error_code: 1, err_desc: err});
        return;
    }

    console.log(req.body.data);

    res.json({error_code: 0, err_desc: null});
})

Answer №2

To retrieve the file, simply access it from req.files and then use fs.writeFile to save it.

fs.readFile(req.files.formInput.path, function (err, data) {
  fs.writeFile(newPath, data, function (err) {
    if (err) {
    throw err;
    }
    console.log("File has been successfully saved");
  });
});

Answer №3

If you want to achieve a similar result, consider the following approach:

          $http({
                url: endpoint, 
                method: 'GET',
                data: json_payload,
                headers: {'Content-Type': 'application/json'}
          }).then(function(response) {
                var responseData = response.data;
                console.log(responseData);
          }, function onFailure(response) {
              // Handle errors in case of failure
          });

Another option is to include the data property inside your function.

    var userDetails = {
    username: $scope.user.username,
    password: $scope.user.password,
    fullName: $scope.user.fullName
    };

    $http.post(uploadEndpoint, formData, {
         transformRequest: angular.identity,
         data: userDetails,
         headers: {'Content-Type': 'application/json'}
    })

For backend processing, test something like this:

req.on('data', function (chunk) {
    console.log(chunk);
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountered MissingSchemaError: The schema for this model has not been registered, mongoose.model was called before defining the schema

I encountered an error with the following stack trace: Starting from my main node server file, where I load routes: require('./config/routes')(app); In my routes file: var todos = require('../app/controllers/todos'); The error occu ...

What is the process for implementing a new requirement for 'confirmed' users when they log in with passport.js?

Looking to enhance the functionality of passport.js by implementing a conditional check to verify if the user account is confirmed. The plan is to insert an 'if statement' towards the end of the code, right after validating the user's email ...

Unable to access the router while attempting to connect through express

I am facing an issue with implementing routers in my Node.js application. I am unable to successfully execute the router.get function. In the main server file, which is named server.js, I have included the following script: // Routes app.use('/api/v1 ...

Error: The prop type validation has failed for `errors` in component `CreateProfile`. The expected type was `object`, but a `string` was

Upon login, I encountered an issue with creating a user profile where the error message states invalid props errors. Both my client and server are up and running, and I am utilizing Redux in my React application. Below is the code for this MERN stack p ...

AngularJS error handling not receiving error response from Asp.Net API

I am using an Ionic app that interacts with an asp.net web API. Within the code, there is a HttpResponseMessage being utilized. [Authorize] [Route("api/products/search/{term}/{page}")] [HttpGet] public HttpResponseMessage SearchProducts(string term, int p ...

While it is possible to filter by friend.brand.id within friends in Angular, unfortunately the || undefined trick cannot be used to reset the filter when it is NULL

In the futuristic world of 2075, immortal humans have subjugated mortal humans. There exists a unique store where mortal friends are sold, and efforts are being made to develop an app that allows customers to manage their friends based on their favorite br ...

Building a basic user authentication system in Node.js with Express, Passport, and MongoDB

I developed a basic login form using Jade and Express located at /login. The data from the form is submitted via POST to /login Initially, I implemented simple string matching logic for authentication (if username== && password==), deciding whethe ...

Passing a message from a directive in AngularJS using event broadcasting

Many developers are incorporating the following code snippet into their projects: $rootScope.$broadcast('someEvent', someParameter); Later, in a specific controller: $rootScope.$on('someEvent', function(event, e){ /* code implementat ...

Firing ng-change with fileModel or input type="file"

Is there a way to trigger ng-change when a change occurs with this file directive? I have implemented a custom file directive for this purpose. The Directive: app.directive('ngFileModel', ['$parse', function($parse) { return { ...

Guide to capturing user input in an Express router after it has been initialized

I currently have the following components in my project: - An app.js file that utilizes the routes specified in index.js - An index.js file where the initial SQL data retrieval is performed - An index.pug file containing a form to collect user input, in ...

Warning: Unhandled promise rejection - Error encountered while trying to add response due to inability to set headers after they have already been sent to the client

After including the line res.status(201).json({ email });, I encountered an error message saying UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client. How can I address this issue? Here is a ...

"The Jade templating engine in Express no longer retains relative directory paths within the href

In my Express web app, I have a Jade view with a specific element. When accessing the current URL http://localhost:3000/location, the page displays a list of locations, each represented by an ID in a hyperlink like: http://localhost:3000/location/1 http: ...

bypassing files in mongodb for paging purposes

I need to retrieve specific documents based on the page count parameter in my GET request. For instance, when I send a GET request to http://localhost:3001/posts?page=2, I want to receive 10 documents per page starting from document 10 to 20. router/posts ...

The React server-side rendering isn't reflecting changes made on the client-side route

Upon the first refresh, both the server and client side are updated; however, subsequent updates only affect the client side when switching pages with react router. For instance, refreshing the page or entering a new URL causes changes on the server and t ...

Distinguishing between AngularJS ng-init and data-ng-initIn AngularJS,

Currently, I am exploring Angular Js and have noticed that some authors use ng-init while others use data-ng-init. Despite my efforts to research, I have been unable to find a clear explanation of the difference between the two. If anyone can shed light on ...

Looking to connect information

I have written the following code and I am trying to bind data to ng-model. When I use ng-model = "value", I can see the value in the text field, but I want to update the value when the text input is changed. <tbody ng-repeat="action in model.editAct ...

How can I retrieve the user id of the current logged-in user in Odoo and Node.js?

I am looking to fetch the user-id of the currently logged in user. To achieve this, I am utilizing the odoo-xmlrpc node package to establish a connection between my express application and an Odoo instance. odoo.execute_kw("res.users", "search_read", para ...

How to switch images with a click using AngularJS

When I try to toggle an image on click, I am facing an issue where clicking on one element also changes the image for another element. I'm struggling to find a solution for this situation. Here is my HTML code: <div id="TestContainer" class="Test ...

Foreign keys in a one-to-many relationship with Sequelize.js

I am in the process of developing a survey application using Node.js/Express and MySQL incorporating Sequelize.js ORM. However, I am encountering difficulties while establishing the relationship between the two models. My goal is to have the Questions&apo ...

Is Angular causing the issue with Datalist not functioning in IE9?

Autocomplete feature using datalist in Angular works perfectly on all browsers except IE9. I even tried the following workaround: <datalist id="associates"> <!--[if IE 9]><select disabled style="display:none"><![endif]--> <o ...