it-swarm.com.de

Wie zu verarbeiten POST Daten in Node.js?

Wie extrahieren Sie Formulardaten (form[method="post"]) und Datei-Uploads, die von der HTTP-Methode POST in Node.js gesendet werden?

Ich habe die Dokumentation gelesen, gegoogelt und nichts gefunden.

function (request, response) {
    //request.post????
}

Gibt es eine Bibliothek oder einen Hack?

536
Ming-Tang

Wenn Sie Express (leistungsstarke, hochwertige Webentwicklung für Node.js) verwenden, können Sie Folgendes tun:

HTML:

<form method="post" action="/">
    <input type="text" name="user[name]">
    <input type="text" name="user[email]">
    <input type="submit" value="Submit">
</form>

JavaScript:

app.use(express.bodyParser());

app.post('/', function(request, response){
    console.log(request.body.user.name);
    console.log(request.body.user.email);
});

AKTUALISIERT am 1. Juni 2016:

Methode oben ist veraltet, verwenden Sie jetzt:

const bodyParser = require("body-parser");

/** bodyParser.urlencoded(options)
 * Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST)
 * and exposes the resulting object (containing the keys and values) on req.body
 */
app.use(bodyParser.urlencoded({
    extended: true
}));

/**bodyParser.json(options)
 * Parses the text as JSON and exposes the resulting object on req.body.
 */
app.use(bodyParser.json());

app.post("/", function (req, res) {
    console.log(req.body.user.name)
});
473
Baggz

Sie können das Modul querystring verwenden:

var qs = require('querystring');

function (request, response) {
    if (request.method == 'POST') {
        var body = '';

        request.on('data', function (data) {
            body += data;

            // Too much POST data, kill the connection!
            // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
            if (body.length > 1e6)
                request.connection.destroy();
        });

        request.on('end', function () {
            var post = qs.parse(body);
            // use post['blah'], etc.
        });
    }
}

Wenn Sie beispielsweise ein input-Feld mit dem Namen age haben, können Sie mit der Variablen post darauf zugreifen:

console.log(post.age);
662
Casey Chu

Stellen Sie sicher, dass die Verbindung abgebrochen wird, wenn jemand versucht, Ihren Arbeitsspeicher zu überfluten!

var qs = require('querystring');

function (request, response) {
    if (request.method == 'POST') {
        var body = '';
        request.on('data', function (data) {
            body += data;
            // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
            if (body.length > 1e6) { 
                // FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
                request.connection.destroy();
            }
        });
        request.on('end', function () {

            var POST = qs.parse(body);
            // use POST

        });
    }
}
137
thejh

Hier ist ein sehr einfacher Wrapper ohne Framework, der auf den anderen hier veröffentlichten Antworten und Artikeln basiert:

var http = require('http');
var querystring = require('querystring');

function processPost(request, response, callback) {
    var queryData = "";
    if(typeof callback !== 'function') return null;

    if(request.method == 'POST') {
        request.on('data', function(data) {
            queryData += data;
            if(queryData.length > 1e6) {
                queryData = "";
                response.writeHead(413, {'Content-Type': 'text/plain'}).end();
                request.connection.destroy();
            }
        });

        request.on('end', function() {
            request.post = querystring.parse(queryData);
            callback();
        });

    } else {
        response.writeHead(405, {'Content-Type': 'text/plain'});
        response.end();
    }
}

Anwendungsbeispiel:

http.createServer(function(request, response) {
    if(request.method == 'POST') {
        processPost(request, response, function() {
            console.log(request.post);
            // Use request.post here

            response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
            response.end();
        });
    } else {
        response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
        response.end();
    }

}).listen(8000);
92
Mahn

Es wird sauberer, wenn Sie Ihre Daten inJSON codieren und diese dann an Node.js senden.

function (req, res) {
    if (req.method == 'POST') {
        var jsonString = '';

        req.on('data', function (data) {
            jsonString += data;
        });

        req.on('end', function () {
            console.log(JSON.parse(jsonString));
        });
    }
}
75
Lewis

Viele Antworten hier sind keine guten Praktiken mehr oder erklären nichts, deshalb schreibe ich das hier.

Wenn der Callback von http.createServer aufgerufen wird, ist der Server tatsächlich alle Header für die Anforderung erhalten, aber es ist möglich, dass die Daten noch nicht empfangen wurden. Daher müssen wir darauf warten. Das http-Anforderungsobjekt (eine http.IncomingMessage-Instanz) ist tatsächlich ein lesbarStream . In lesbaren Streams, wenn ein Datenblock ankommt, wird ein dataEreignis ausgelöst (vorausgesetzt, Sie haben einen Rückruf registriert) und wenn alle Chunks end eingetroffen sind. _ Ereignis wird ausgegeben. Hier ein Beispiel, wie Sie die Ereignisse hören: 

http.createServer((request, response) => {
  console.log('Now we have a http message with headers but no data yet.');
  request.on('data', chunk => {
    console.log('A chunk of data has arrived: ', chunk);
  });
  request.on('end', () => {
    console.log('No more data');
  })
}).listen(8080)

Wenn Sie dies versuchen, werden Sie feststellen, dass die Blöcke Puffer sind. Wenn Sie sich nicht mit Binärdaten befassen und stattdessen mit Strings arbeiten müssen, empfehle ich die Methode request.setEncoding , die dazu führt, dass der Stream Strings mit der angegebenen Codierung interpretiert und Multibyte-Zeichen ordnungsgemäß verarbeitet.

Jetzt interessieren Sie sich wahrscheinlich nicht für jeden Block, so dass Sie ihn in diesem Fall wahrscheinlich wie folgt puffern möchten:

http.createServer((request, response) => {
  const chunks = [];
  request.on('data', chunk => chunks.Push(chunk));
  request.on('end', () => {
    const data = Buffer.concat(chunks);
    console.log('Data: ', data);
  })
}).listen(8080)

Hier wird Buffer.concat verwendet, das einfach alle Puffer verkettet und einen großen Puffer zurückgibt. Sie können auch das concat-stream-Modul verwenden, das dasselbe tut:

const http = require('http');
const concat = require('concat-stream');
http.createServer((request, response) => {
  concat(request, data => {
    console.log('Data: ', data);
  });
}).listen(8080)

Wenn Sie versuchen, HTML-Formulare POST ohne Dateien anzunehmen oder jQuery ajax -Aufrufe mit dem Standardinhaltstyp zu übergeben, lautet der Inhaltstyp application/x-www-form-urlencoded mit uft-8-Kodierung. Sie können das Querystring-Modul verwenden, um es zu deserialisieren und auf die Eigenschaften zuzugreifen:

const http = require('http');
const concat = require('concat-stream');
const qs = require('querystring');
http.createServer((request, response) => {
  concat(request, buffer => {
    const data = qs.parse(buffer.toString());
    console.log('Data: ', data);
  });
}).listen(8080)

Wenn Sie stattdessen JSON als Inhaltstyp verwenden, können Sie einfach JSON.parse anstelle von qs.parse verwenden.

Wenn Sie sich mit Dateien oder mit mehrteiligen Inhaltstypen befassen, sollten Sie in diesem Fall so etwas wie Formidable verwenden, das den Umgang mit den Dateien mit allen Mitteln beseitigt. Schauen Sie sich diese andere Antwort von mir an, wo ich hilfreiche Links und Module für mehrteilige Inhalte gepostet habe.

Wenn Sie den Inhalt nicht parsen möchten, sondern ihn an eine andere Stelle weiterleiten möchten, z. B. als andere Daten an eine andere http-Anfrage senden oder in einer Datei speichern, empfehle ich piping anstatt sie zu puffern. Da es weniger Code ist, der Gegendruck besser verarbeitet wird, wird weniger Speicher benötigt und in manchen Fällen auch schneller.

Wenn Sie also den Inhalt in einer Datei speichern möchten:

 http.createServer((request, response) => {
   request.pipe(fs.createWriteStream('./request'));
 }).listen(8080)

Wie andere Antworten feststellten, denke ich daran, dass böswillige Clients Ihnen eine riesige Datenmenge senden können, um Ihre Anwendung zum Absturz zu bringen oder Ihren Speicher zu füllen, um sicherzustellen, dass Sie Anforderungen ablegen, bei denen Daten eine bestimmte Grenze überschreiten. Wenn Sie keine Bibliothek verwenden, um die eingehenden Daten zu verarbeiten. Ich würde vorschlagen, etwas wie stream-meter zu verwenden, das die Anfrage abbrechen kann, wenn das angegebene Limit erreicht wird:

limitedStream = request.pipe(meter(1e7));
limitedStream.on('data', ...);
limitedStream.on('end', ...);

oder 

request.pipe(meter(1e7)).pipe(createWriteStream(...));

oder 

concat(request.pipe(meter(1e7)), ...);

Versuchen Sie auch, npm-Module zu verwenden, anstatt sie selbst zu implementieren, da sie Edge-Fälle wahrscheinlich besser verarbeiten können. Für Express empfehle ich die Verwendung von Body-Parser . Für Koa gibt es ein ähnliches Modul .

Wenn Sie kein Framework verwenden, ist body ziemlich gut.

74

Für alle, die sich fragen, wie sie diese triviale Aufgabe erledigen können, ohne ein Web-Framework zu installieren, ist es mir gelungen, dies gemeinsam zu erledigen. Kaum serienreif, aber es scheint zu funktionieren.

function handler(req, res) {
    var POST = {};
    if (req.method == 'POST') {
        req.on('data', function(data) {
            data = data.toString();
            data = data.split('&');
            for (var i = 0; i < data.length; i++) {
                var _data = data[i].split("=");
                POST[_data[0]] = _data[1];
            }
            console.log(POST);
        })
    }
}
33
Shawn Whinnery

Sie können body-parser verwenden, den Node.js-Body, der Middleware analysiert.

Erstes Laden body-parser 

$ npm install body-parser --save

Ein Beispielcode

var express = require('express')
var bodyParser = require('body-parser')

var app = express()

app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())


app.use(function (req, res) {
  var post_data = req.body;
  console.log(post_data);
})

Weitere Dokumentation finden Sie hier

9
sourcecode

Referenz: https://nodejs.org/de/docs/guides/anatomy-of-an-hthtp-transaction/

let body = [];
request.on('data', (chunk) => {
  body.Push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // at this point, `body` has the entire request body stored in it as a string
});
8
Udhaya

So können Sie dies tun, wenn Sie node-formidable verwenden:

var formidable = require("formidable");

var form = new formidable.IncomingForm();
form.parse(request, function (err, fields) {
    console.log(fields.parameter1);
    console.log(fields.parameter2);
    // ...
});
6
Dmitry

1) Installieren Sie 'body-parser' von npm.

2) Dann in Ihrer App.ts  

var bodyParser = require('body-parser');

3) dann musst du schreiben 

app.use(bodyParser.json())

in app.ts module

4) Denken Sie daran, dass Sie mit einschließen 

app.use(bodyParser.json())

oben oder vor einer Moduldeklaration.

Ex: 

app.use(bodyParser.json())
app.use('/user',user);

5) Dann verwenden 

var postdata = req.body;
4

Wenn Sie Ihre Daten nicht mit dem data-Callback zusammenfassen möchten, können Sie den readable-Callback immer wie folgt verwenden:

// Read Body when Available
request.on("readable", function(){
  request.body = '';
  while (null !== (request.body += request.read())){}
});

// Do something with it
request.on("end", function(){
  request.body //-> POST Parameters as String
});

Bei diesem Ansatz wird die eingehende Anforderung geändert. Sobald Sie Ihre Antwort jedoch beendet haben, wird die Anforderung als Müll gesammelt, sodass dies kein Problem sein sollte.

Ein fortgeschrittener Ansatz wäre, zuerst die Körpergröße zu überprüfen, wenn Sie Angst vor großen Körpern haben.

4

Sie müssen die POST-Daten in Abschnitten mit request.on('data', function(chunk) {...}) empfangen.

const http = require('http');

http.createServer((req, res) => {
    if (req.method == 'POST') {
        whole = ''
        req.on('data', (chunk) => {
            # consider adding size limit here
            whole += chunk.toString()
        })

        req.on('end', () => {
            console.log(whole)
            res.writeHead(200, 'OK', {'Content-Type': 'text/html'})
            res.end('Data received.')
        })
    }
}).listen(8080)

Sie sollten in Betracht ziehen, an der angegebenen Position ein Größenlimit hinzuzufügen, als thejh vorgeschlagen .

4
Zaz

Es gibt mehrere Möglichkeiten, dies zu tun. Der schnellste Weg, den ich kenne, ist jedoch die Verwendung der Express.js-Bibliothek mit Body-Parser.

var express = require("express");
var bodyParser = require("body-parser");
var app = express();

app.use(bodyParser.urlencoded({extended : true}));

app.post("/pathpostdataissentto", function(request, response) {
  console.log(request.body);
  //Or
  console.log(request.body.fieldName);
});

app.listen(8080);

Das kann für Strings funktionieren, aber ich würde stattdessen bodyParser.urlencoded in bodyParser.json ändern, wenn die POST - Daten ein JSON-Array enthalten.

Weitere Informationen: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/

4
nikodean2

Wenn Sie Express.js verwenden, müssen Sie vor dem Zugriff auf den erforderlichen Körper Middleware bodyParser hinzufügen:

app.use(express.bodyParser());

Dann kannst du fragen

req.body.user
3
PatricioS

Wenn Sie es vorziehen, reine Node.js zu verwenden, können Sie POST Daten wie unten gezeigt extrahieren:

// Dependencies
const StringDecoder = require('string_decoder').StringDecoder;
const http = require('http');

// Instantiate the HTTP server.
const httpServer = http.createServer((request, response) => {
  // Get the payload, if any.
  const decoder = new StringDecoder('utf-8');
  let payload = '';

  request.on('data', (data) => {
    payload += decoder.write(data);
  });

  request.on('end', () => {
    payload += decoder.end();

    // Parse payload to object.
    payload = JSON.parse(payload);

    // Do smoething with the payload....
  });
};

// Start the HTTP server.
const port = 3000;
httpServer.listen(port, () => {
  console.log(`The server is listening on port ${port}`);
});

3

Und wenn Sie nicht das gesamte Framework wie Express verwenden möchten, sondern auch verschiedene Arten von Formularen, einschließlich Uploads, benötigen, ist formaline möglicherweise eine gute Wahl.

Es ist in Node.js-Modulen aufgeführt

2
Pavel Koryagin

Sie können die express middleware verwenden, in die jetzt ein Body-Parser eingebaut ist. Das bedeutet, dass Sie Folgendes tun müssen:

import express from 'express'

const app = express()

app.use(express.json())

app.post('/thing', (req, res) => {
  console.log(req.body) // <-- this will access the body of the post
  res.sendStatus(200)
})

Dieses Codebeispiel ist ES6 mit Express 4.16.x

1
Big Money

Ich habe ein Video gefunden, in dem erklärt wird, wie Sie dies erreichen können: https://www.youtube.com/watch?v=nuw48-u3Yrg

Es verwendet das Standardmodul "http" zusammen mit den Modulen "querystring" und "stringbuilder". Die Anwendung bezieht zwei Zahlen (mit zwei Textfeldern) von einer Webseite und gibt beim Senden die Summe dieser Zahlen zurück (zusammen mit dem Behalten der Werte in den Textfeldern). Dies ist das beste Beispiel, das ich anderswo finden könnte.

Zugehöriger Quellcode:

var http = require("http");
var qs = require("querystring");
var StringBuilder = require("stringbuilder");

var port = 9000;

function getCalcHtml(req, resp, data) {
    var sb = new StringBuilder({ newline: "\r\n" });
    sb.appendLine("<html>");
    sb.appendLine(" <body>");
    sb.appendLine("     <form method='post'>");
    sb.appendLine("         <table>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td>Enter First No: </td>");

    if (data && data.txtFirstNo) {
        sb.appendLine("                 <td><input type='text' id='txtFirstNo' name='txtFirstNo' value='{0}'/></td>", data.txtFirstNo);
    }
    else {
        sb.appendLine("                 <td><input type='text' id='txtFirstNo' name='txtFirstNo' /></td>");
    }

    sb.appendLine("             </tr>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td>Enter Second No: </td>");

    if (data && data.txtSecondNo) {
        sb.appendLine("                 <td><input type='text' id='txtSecondNo' name='txtSecondNo' value='{0}'/></td>", data.txtSecondNo);
    }
    else {
        sb.appendLine("                 <td><input type='text' id='txtSecondNo' name='txtSecondNo' /></td>");
    }

    sb.appendLine("             </tr>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td><input type='submit' value='Calculate' /></td>");
    sb.appendLine("             </tr>");

    if (data && data.txtFirstNo && data.txtSecondNo) {
        var sum = parseInt(data.txtFirstNo) + parseInt(data.txtSecondNo);
        sb.appendLine("             <tr>");
        sb.appendLine("                 <td>Sum: {0}</td>", sum);
        sb.appendLine("             </tr>");
    }

    sb.appendLine("         </table>");
    sb.appendLine("     </form>")
    sb.appendLine(" </body>");
    sb.appendLine("</html>");
    sb.build(function (err, result) {
        resp.write(result);
        resp.end();
    });
}

function getCalcForm(req, resp, data) {
    resp.writeHead(200, { "Content-Type": "text/html" });
    getCalcHtml(req, resp, data);
}

function getHome(req, resp) {
    resp.writeHead(200, { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>Home</title></head><body>Want to some calculation? Click <a href='/calc'>here</a></body></html>");
    resp.end();
}

function get404(req, resp) {
    resp.writeHead(404, "Resource Not Found", { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>404</title></head><body>404: Resource not found. Go to <a href='/'>Home</a></body></html>");
    resp.end();
}

function get405(req, resp) {
    resp.writeHead(405, "Method not supported", { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>405</title></head><body>405: Method not supported</body></html>");
    resp.end();
}

http.createServer(function (req, resp) {
    switch (req.method) {
        case "GET":
            if (req.url === "/") {
                getHome(req, resp);
            }
            else if (req.url === "/calc") {
                getCalcForm(req, resp);
            }
            else {
                get404(req, resp);
            }
            break;
        case "POST":
            if (req.url === "/calc") {
                var reqBody = '';
                req.on('data', function (data) {
                    reqBody += data;
                    if (reqBody.length > 1e7) { //10MB
                        resp.writeHead(413, 'Request Entity Too Large', { 'Content-Type': 'text/html' });
                        resp.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
                    }
                });
                req.on('end', function () {
                    var formData = qs.parse(reqBody);
                    getCalcForm(req, resp, formData);
                });
            }
            else {
                get404(req, resp);
            }
            break;
        default:
            get405(req, resp);
            break;
    }
}).listen(port);
1
user203687

Für diejenigen, die raw binary POST upload verwenden, können Sie Folgendes verwenden:

Klient:

var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
var blob = new Uint8Array([65,72,79,74]); // or e.g. recorder.getBlob()
xhr.send(blob);

Server:

var express = require('express');
var router = express.Router();
var fs = require('fs');

router.use (function(req, res, next) {
  var data='';
  req.setEncoding('binary');
  req.on('data', function(chunk) {
    data += chunk;
  });

  req.on('end', function() {
    req.body = data;
    next();
  });
});

router.post('/api/upload', function(req, res, next) {
  fs.writeFile("binaryFile.png", req.body, 'binary', function(err) {
    res.send("Binary POST successful!");
  });
});
1
lukyer

Sie können die Antwort der POST - Anforderung einfach senden und abrufen, indem Sie "Request - Simplified HTTP client" und Javascript Promise verwenden. 

var request = require('request');

function getData() {
    var options = {
        url: 'https://example.com',
        headers: {
            'Content-Type': 'application/json'
        }
    };

    return new Promise(function (resolve, reject) {
        var responseData;
        var req = request.post(options, (err, res, body) => {
            if (err) {
                console.log(err);
                reject(err);
            } else {
                console.log("Responce Data", JSON.parse(body));
                responseData = body;
                resolve(responseData);
            }
        });
    });
}
0

Wenn es sich um einen Dateiupload handelt, sendet der Browser sie normalerweise als "multipart/form-data"-Inhaltstyp . Sie können diesen in solchen Fällen verwenden

var multipart = require('multipart');
multipart.parse(req)

Referenz 1

Referenz 2

0
user3526

sie können Post-Parameter ohne Verwendung von Express extrahieren.

1: nmp install multiparty

2: Multiparty importieren. als var multiparty = require('multiparty');

3: `

if(req.method ==='POST'){
   var form = new multiparty.Form();
   form.parse(req, function(err, fields, files) {
      console.log(fields['userfile1'][0]);
    });
    }

4: und HTML FORM IS.

<form method=POST enctype=multipart/form-data>
<input type=text name=userfile1><br>
<input type=submit>
</form>

Ich hoffe das wird für dich funktionieren. Vielen Dank.

0
Maneesh Singh

Sie müssen bodyParser () verwenden, wenn die Formulardaten in req.body verfügbar sein sollen. body-parser analysiert Ihre Anfrage und konvertiert sie in ein Format, aus dem Sie leicht relevante Informationen extrahieren können, die Sie möglicherweise benötigen.

Angenommen, Sie haben ein Anmeldeformular an Ihrem Frontend. Sie füllen es aus und fordern den Server auf, die Details irgendwo zu speichern.

Das Extrahieren von Benutzernamen und Passwort aus Ihrer Anfrage geht so einfach wie unten, wenn Sie Body-Parser verwenden.

…………………………………………………….

var loginDetails = {

username : request.body.username,

password : request.body.password

};
0
Rubin bhandari

Auf Formularfeldern wie diesen 

   <input type="text" name="user[name]" value="MyName">
   <input type="text" name="user[email]" value="[email protected]">

einige der oben genannten Antworten schlagen fehl, da sie nur Flat Data unterstützen.

Im Moment verwende ich die Casey Chu-Antwort, jedoch mit "qs" anstelle des Moduls "Querystring". Dies ist das Modul "Body-Parser" , das ebenfalls verwendet wird. Wenn Sie also verschachtelte Daten wünschen, müssen Sie qs installieren. 

npm install qs --save

Dann ersetzen Sie die erste Zeile wie folgt:

//var qs = require('querystring');
var qs = require('qs'); 

function (request, response) {
    if (request.method == 'POST') {
        var body = '';

        request.on('data', function (data) {
            body += data;

            // Too much POST data, kill the connection!
            // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
            if (body.length > 1e6)
                request.connection.destroy();
        });

        request.on('end', function () {
            var post = qs.parse(body);
            console.log(post.user.name); // should work
            // use post['blah'], etc.
        });
    }
}
0
Geza Turi

Limit POST Größe vermeiden, um Ihre Knoten-App zu überschwemmen. Es gibt ein großes raw-body -Modul, das sich sowohl für Express- als auch für Connect-Verbindungen eignet.

0
EricSonaron