Comment extraire les données POST dans Node.js?

Comment extraire les données de formulaire ( form[method="post"] ) et les envois de fichiers envoyés par la méthode HTTP POST dans Node.js ?

J’ai lu la documentation, googlé et n’a rien trouvé.

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

Y a-t-il une bibliothèque ou un hack?

    Si vous utilisez Express (développement Web haut de gamme et performant pour Node.js), vous pouvez le faire:

    HTML:

     

    JavaScript:

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

    MIS À JOUR le 1 / juin / 2016:

    La méthode ci-dessus est une utilisation obsolète maintenant:

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

    Vous pouvez utiliser le module de queryssortingng :

     var qs = require('queryssortingng'); 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. }); } } 

    Maintenant, par exemple, si vous avez un champ de input avec le nom age , vous pouvez y accéder à l’aide de la variable post :

     console.log(post.age); 

    Assurez-vous de tuer la connexion si quelqu’un essaie d’inonder votre RAM!

     var qs = require('queryssortingng'); 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 }); } } 

    Voici un wrapper sans framework très simple basé sur les autres réponses et articles publiés ici:

     var http = require('http'); var queryssortingng = require('queryssortingng'); 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 = queryssortingng.parse(queryData); callback(); }); } else { response.writeHead(405, {'Content-Type': 'text/plain'}); response.end(); } } 

    Exemple d’utilisation:

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

    Ce sera plus propre si vous encodez vos données en JSON , puis envoyez-les à Node.js.

     function (req, res) { if (req.method == 'POST') { var jsonSsortingng = ''; req.on('data', function (data) { jsonSsortingng += data; }); req.on('end', function () { console.log(JSON.parse(jsonSsortingng)); }); } } 

    Beaucoup de réponses ici ne sont plus de bonnes pratiques ou n’expliquent rien, alors c’est pourquoi j’écris ceci.

    Lorsque le rappel de http.createServer est appelé, c’est lorsque le serveur a effectivement reçu tous les en-têtes de la demande, mais il est possible que les données n’aient pas encore été reçues, nous devons donc l’attendre. L’ object de requête http (une instance http.IncomingMessage) est en réalité un stream lisible . Dans les stream lisibles à chaque fois qu’un bloc de données arrive, un événement de data est émis (en supposant que vous ayez enregistré un rappel) et lorsque tous les blocs sont arrivés, un événement de end est émis. Voici un exemple sur la façon dont vous écoutez les événements:

     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) 

    Si vous essayez ceci, vous remarquerez que les morceaux sont des tampons . Si vous ne traitez pas de données binarys et que vous avez besoin de travailler avec des chaînes, je vous suggère d’utiliser la méthode request.setEncoding qui provoque l’interprétation des chaînes d’émission avec le codage donné et gère correctement les caractères multi-octets.

    Maintenant, vous n’êtes probablement pas intéressé par chaque morceau par lui-même, alors dans ce cas, vous voulez probablement le tamponner comme ceci:

     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) 

    Ici, Buffer.concat est utilisé, qui concatène simplement tous les tampons et renvoie un gros tampon. Vous pouvez également utiliser le module concat-stream qui fait la même chose:

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

    Si vous essayez d’accepter la soumission POST de formulaires HTML sans fichiers ou de passer des appels ajax jQuery avec le type de contenu par défaut, le type de contenu est application/x-www-form-urlencoded avec uft-8 codage uft-8 . Vous pouvez utiliser le module queryssortingng pour le désérialiser et accéder aux propriétés:

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

    Si votre type de contenu est JSON, vous pouvez simplement utiliser JSON.parse au lieu de qs.parse .

    Si vous traitez des fichiers ou manipulez un type de contenu en plusieurs parties, alors, dans ce cas, vous devriez utiliser quelque chose de formidable qui élimine toutes les difficultés. Jetez un coup d’œil à cette autre réponse , où j’ai posté des liens et des modules utiles pour du contenu en plusieurs parties.

    Si vous ne voulez pas parsingr le contenu mais le transmettre à un autre endroit, par exemple, l’envoyer à une autre requête http en tant que donnée ou l’enregistrer dans un fichier, je vous suggère de le filtrer plutôt que de le mettre en mémoire tampon, car ce sera moins code, gère mieux la contre-pression, il faudra moins de mémoire et dans certains cas plus rapidement.

    Donc, si vous voulez enregistrer le contenu dans un fichier:

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

    Comme d’autres réponses l’ont noté, gardez à l’esprit que les clients malveillants peuvent vous envoyer une quantité énorme de données pour faire planter votre application ou remplir votre mémoire afin de protéger les requêtes émettant des données d’une certaine limite. Si vous n’utilisez pas de bibliothèque pour gérer les données entrantes. Je suggère d’utiliser quelque chose comme stream-meter qui peut annuler la demande si atteint la limite spécifiée:

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

    ou

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

    ou

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

    Essayez également d’utiliser les modules npm plutôt que de les implémenter vous-même, car ils traiteront probablement mieux les cas de pointe. Pour exprimer, je suggère d’utiliser un parsingur de corps . Pour koa, il y a un module similaire .

    Si vous n’utilisez pas de cadre, le corps est plutôt bon.

    Pour quiconque se demande comment faire cette tâche sortingviale sans avoir à installer un framework Web, j’ai réussi à le regrouper. Difficile à produire mais ça semble marcher.

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

    Vous pouvez utiliser body-parser , le middleware d’parsing de corps Node.js.

    Premier body-parser

     $ npm install body-parser --save 

    Un exemple de code

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

    Plus de documentation peut être trouvé ici

    Référence: https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/

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

    Voici comment vous pouvez le faire si vous utilisez node-formidable :

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

    Si vous ne voulez pas fragmenter vos données avec le rappel de data vous pouvez toujours utiliser le rappel readable comme ceci:

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

    Cette approche modifie la demande entrante, mais dès que vous avez terminé votre réponse, la demande sera supprimée, ce qui ne devrait pas poser de problème.

    Une approche avancée serait de vérifier d’abord la taille du corps, si vous avez peur des corps énormes.

    Il y a plusieurs façons de le faire. Cependant, le moyen le plus rapide est d’utiliser la bibliothèque Express.js avec 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); 

    Cela peut fonctionner pour les chaînes, mais je remplacerais plutôt bodyParser.urlencoded par bodyParser.json si les données POST contiennent un tableau JSON.

    Plus d’infos: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/

    Vous devez recevoir les données POST en morceaux en utilisant request.on('data', function(chunk) {...})

     const http = require('http'); http.createServer((req, res) => { if (req.method == 'POST') { whole = '' req.on('data', (chunk) => { # consider adding size limit here whole += chunk.toSsortingng() }) req.on('end', () => { console.log(whole) res.writeHead(200, 'OK', {'Content-Type': 'text/html'}) res.end('Data received.') }) } }).listen(8080) 

    Vous devriez envisager d’append une limite de taille à la position indiquée, comme suggéré .

    Si vous utilisez Express.js , avant de pouvoir accéder à req.body, vous devez append middleware bodyParser:

     app.use(express.bodyParser()); 

    Alors vous pouvez demander

     req.body.user 

    Et si vous ne souhaitez pas utiliser le framework complet comme Express, mais que vous avez également besoin de différents types de formulaires, y compris de téléchargements, le formalisme peut être un bon choix.

    Il est répertorié dans les modules Node.js

    1. Installez 'body-parser' partir de npm.
    2. puis ouvrez app.ts -> write -> var bodyParser = require('body-parser');
    3. alors vous devez écrire app.use(bodyParser.json()) dans le module app.ts
    4. N’oubliez pas que vous incluez app.use(bodyParser.json()) en haut ou avant toute déclaration de module. Ex: app.use(bodyParser.json()) app.use('/user',user);

    5. Ensuite, utilisez var postdata = req.body;

    Pour ceux qui utilisent le téléchargement POST binary brut sans encoder la surcharge, vous pouvez utiliser:

    client:

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

    serveur:

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

    La taille limite du POST évite d’inonder votre application de noeud. Il existe un excellent module de corps brut , adapté à la fois à l’expression et à la connexion, qui peut vous aider à limiter les demandes en fonction de leur taille et de leur longueur.

    J’ai trouvé une vidéo expliquant comment y parvenir: https://www.youtube.com/watch?v=nuw48-u3Yrg

    Il utilise le module “http” par défaut avec les modules “queryssortingng” et “ssortingngbuilder”. L’application prend deux nombres (à l’aide de deux zones de texte) à partir d’une page Web et, après soumission, renvoie la sum de ces deux éléments (avec la persistance des valeurs dans les zones de texte). C’est le meilleur exemple que je puisse trouver ailleurs.

    Code source associé:

     var http = require("http"); var qs = require("queryssortingng"); var SsortingngBuilder = require("ssortingngbuilder"); var port = 9000; function getCalcHtml(req, resp, data) { var sb = new SsortingngBuilder({ newline: "\r\n" }); sb.appendLine(""); sb.appendLine(" "); sb.appendLine(" 
    "); sb.appendLine(" "); sb.appendLine(" "); sb.appendLine(" "); if (data && data.txtFirstNo) { sb.appendLine(" ", data.txtFirstNo); } else { sb.appendLine(" "); } sb.appendLine(" "); sb.appendLine(" "); sb.appendLine(" "); if (data && data.txtSecondNo) { sb.appendLine(" ", data.txtSecondNo); } else { sb.appendLine(" "); } sb.appendLine(" "); sb.appendLine(" "); sb.appendLine(" "); sb.appendLine(" "); if (data && data.txtFirstNo && data.txtSecondNo) { var sum = parseInt(data.txtFirstNo) + parseInt(data.txtSecondNo); sb.appendLine(" "); sb.appendLine(" ", sum); sb.appendLine(" "); } sb.appendLine("
    Enter First No:
    Enter Second No:
    Sum: {0}
    "); sb.appendLine("
    ") sb.appendLine(" "); sb.appendLine(""); 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("HomeWant to some calculation? Click here"); resp.end(); } function get404(req, resp) { resp.writeHead(404, "Resource Not Found", { "Content-Type": "text/html" }); resp.write("404404: Resource not found. Go to Home"); resp.end(); } function get405(req, resp) { resp.writeHead(405, "Method not supported", { "Content-Type": "text/html" }); resp.write("405405: Method not supported"); resp.end(); } http.createServer(function (req, resp) { switch (req.method) { case "GET": if (req.url === "/") { getHome(req, resp); } else if (req.url === "https://stackoverflow.com/calc") { getCalcForm(req, resp); } else { get404(req, resp); } break; case "POST": if (req.url === "https://stackoverflow.com/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('413413: Request Entity Too Large'); } }); 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);

    S’il s’agit d’un téléchargement de fichier, le navigateur l’envoie généralement en tant que type de contenu "multipart/form-data" . Vous pouvez l’utiliser dans de tels cas

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

    Référence 1

    Référence 2

    Sur des champs de formulaire comme ceux-ci

        

    Certaines des réponses ci-dessus échoueront car elles ne supportent que des données plates.

    Pour l’instant j’utilise la réponse de Casey Chu mais avec le “qs” au lieu du module “queryssortingng”. C’est le module utilisé par “body-parser” . Donc, si vous voulez des données nestedes, vous devez installer qs.

     npm install qs --save 

    Puis remplacez la première ligne comme:

     //var qs = require('queryssortingng'); 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. }); } } 

    vous pouvez extraire post paramètre sans utiliser express.

    1: nmp install multiparty

    2: import multipartite. comme 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: et HTML FORM IS.

     

    J’espère que cela fonctionnera pour vous. Merci.