web-dev-qa-db-ja.com

処理方法 POST Node.js内のデータ

Node.js のHTTP POSTメソッドから送信されたフォームデータ(form[method="post"])とファイルアップロードをどのように抽出しますか?

私はドキュメントを読み、グーグルしても何も見つかりませんでした。

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

図書館やハックはありますか?

553
Ming-Tang

Express (Node.js用の高性能でハイクラスのWeb開発)を使用する場合は、これを実行できます。

HTML:

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

APIクライアント:

fetch('/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        user: {
            name: "John",
            email: "[email protected]"
        }
    })
});

Node.js: (Express v4.16.0以降)

// Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded());

// Parse JSON bodies (as sent by API clients)
app.use(express.json());

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

Node.js: (Express <4.16.0の場合)

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

querystring モジュールを使うことができます。

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

たとえば、inputという名前のageフィールドがある場合は、変数postを使用してアクセスできます。

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

誰かがあなたのRAMをあふれさせようとした場合は、必ず接続を切断してください。

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

        });
    }
}
142
thejh

ここに掲載されている他の回答と記事に基づいた、非常に単純なフレームワークなしのラッパーです。

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

使用例

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

ここでの多くの答えは、もはや良い習慣ではない、あるいは何も説明していないので、私はこれを書いているのです。

Http.createServerのコールバックが呼び出されるときは、サーバーが実際に要求のすべてのヘッダーを受け取ったときですが、まだデータが受け取られていない可能性があるので、それを待つ必要があります。 httpリクエストオブジェクト(http.IncomingMessageインスタンス) は実際には 読み取り可能ストリーム です。読み込み可能なストリームでは、データの塊が到着するたびに dataイベントが発行される (すべての塊が到着すると) end イベントが発生します。これがあなたがイベントをどう聞くかの例です:

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)

これを試すと、チャンクが buffers であることがわかります。バイナリデータを扱っておらず、代わりに文字列を扱う必要がある場合は、 request.setEncoding メソッドを使用することをお勧めします。これにより、ストリームは指定のエンコードで解釈された文字列を生成し、マルチバイト文字を正しく処理します。

今、あなたはたぶんそれ自身で各チャンクに興味を持っていないでしょう、それでこの場合このようにそれをバッファしたいと思うでしょう:

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)

ここでは Buffer.concat が使用されています。これは単純にすべてのバッファを連結して1つの大きなバッファを返します。同じことをする concat-stream module を使うこともできます。

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

HTML形式のPOSTファイルを指定せずに送信を受け入れる場合、またはデフォルトのコンテンツタイプで jQuery ajax 呼び出しを処理する場合、コンテンツタイプはapplication/x-www-form-urlencodedエンコーディングでuft-8になります。 querystring module を使用して逆シリアル化し、プロパティにアクセスすることができます。

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)

コンテンツタイプが代わりにJSONの場合は、 qs.parse の代わりに単に JSON.parse を使用できます。

ファイルを扱っている場合、またはマルチパートコンテンツタイプを処理している場合は、その場合は、formidableのようなものを使用する必要があります。私がマルチパートコンテンツのための役に立つリンクとモジュールを投稿したところで私の この他の答え を見てください。

内容を解析したくない場合は、他の場所に渡します。たとえば、データとして別のhttpリクエストに送信するか、ファイルに保存します。バッファリングするのではなく、 pipeing を推奨します。コードが少なくて済むため、バックプレッシャーを適切に処理できます。メモリ使用量も少なくなり、場合によっては高速になります。

あなたがファイルに内容を保存したいのであれば:

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

他の回答が指摘したように、悪意のあるクライアントがあなたのアプリケーションをクラッシュさせたりメモリをいっぱいにするために大量のデータをあなたに送ってあなたがデータを発するリクエストを落とすのを確実に制限するということを覚えておいてください。着信データを処理するためにライブラリを使用しない場合私は stream-meter のようなものを使うことを提案します。

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

または

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

または

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

また、おそらくEdgeのケースをよりうまく処理できるように、npmモジュールを自分で実装するのではなく使用するようにしてください。明白のために私は body-parser を使うことを提案します。コアの場合、 同様のモジュール があります。

フレームワークを使用しない場合は、 body が非常に優れています。

79

データを _ json _ にエンコードしてからNode.jsに送信すると、よりクリーンになります。

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

Webフレームワークをインストールせずにこの簡単なタスクを実行する方法を疑問に思う人は、私はこれを一緒に開発しました。ほとんど生産準備はできていませんが、うまくいくようです。

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);
        })
    }
}
34
Shawn Whinnery

Node.jsの本体解析ミドルウェアであるbody-parserを使用できます。

最初にロードするbody-parser

$ npm install body-parser --save

いくつかのサンプルコード

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

より多くのドキュメントを見つけることができます ここ

10
sourcecode

参照: 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).toString();
  // at this point, `body` has the entire request body stored in it as a string
});
9
Udhaya

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

1)npmから'body-parser'をインストールしてください。

2)それから app.ts

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

3)それからあなたは書く必要があります

app.use(bodyParser.json())

app.ts moduleに

4)あなたが含めることを覚えておいてください

app.use(bodyParser.json())

モジュール宣言の先頭または前に。

例:

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

5)それから

var postdata = req.body;
5

dataコールバックと一緒にデータをチャンクしたくない場合は、常に次のようにreadableコールバックを使用できます。

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

このアプローチは入ってくるリクエストを修正します、しかしあなたがあなたのレスポンスを終えるとすぐにリクエストはガベージコレクションされるでしょう、それでそれは問題であるべきではありません。

あなたが巨大な体を恐れているならば、高度なアプローチは最初に体の大きさをチェックすることでしょう。

4

純粋なNode.jsを使用したい場合は、以下に示すようにPOST dataを抽出します。

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

request.on('data', function(chunk) {...})を使ってPOSTデータをまとまりで受け取る必要があります。

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)

示された位置に thejhが提案した のようにサイズ制限を追加することを検討してください。

4
Zaz

それをするには複数の方法があります。しかし、私が知っている最も早い方法は、body.jarでExpress.jsライブラリを使用することです。

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

これは文字列に対しても機能しますが、POST dataにJSON配列が含まれる場合は、代わりにbodyParser.urlencodedをbodyParser.jsonに変更します。

より多くの情報: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/

4
nikodean2

Express.js を使用している場合は、req.bodyにアクセスする前にミドルウェアbodyParserを追加する必要があります。

app.use(express.bodyParser());

それからあなたは求めることができます

req.body.user
3
PatricioS

Expressのようにフレームワーク全体を使いたくないが、アップロードを含むさまざまな種類のフォームも必要な場合は、 formaline が適しています。

Node.jsモジュールにリストされています

2
Pavel Koryagin

express ミドルウェアを使用することができます。これにはボディパーサーが組み込まれています。これは、あなたがする必要があるのは以下のことだけであることを意味します。

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

そのコード例は、Express 4.16.xを使用したES6です。

1
Big Money

私はこれを達成する方法について説明したビデオを見つけました: https://www.youtube.com/watch?v=nuw48-u3Yrg

それは "querystring"と "stringbuilder"モジュールと共にデフォルトの "http"モジュールを使います。アプリケーションはWebページから2つの数字(2つのテキストボックスを使用)を取得し、送信時にこれら2つの合計を(テキストボックス内の値を保持しながら)返します。これは私が他の場所で見つけることができる最も良い例です。

関連するソースコード:

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

生のバイナリPOST upload を使用している場合は、エンコードのオーバーヘッドなしで次のように使用できます。

クライアント:

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

サーバー:

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

"Request - Simplified HTTP client"とJavascript Promiseを使用すると、POST requestの応答を簡単に送信および取得できます。

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

ファイルのアップロードが含まれる場合、ブラウザは通常、それを"multipart/form-data"コンテンツタイプとして送信します。そのような場合にこれを使うことができます

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

参考文献1

参考文献2

0
user3526

expressを使わずにpostパラメータを抽出することができます。

1:nmp install multiparty

2:マルチパーティをインポートします。 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:およびHTMLフォームIS。

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

私はこれがあなたのために働くことを願っています。ありがとう。

0
Maneesh Singh

フォームデータをreq.bodyで利用できるようにしたい場合は、bodyParser()を使用する必要があります。 body-parserはあなたのリクエストを解析し、それをあなたが必要とするかもしれない関連情報を簡単に抽出できるフォーマットに変換します。

たとえば、フロントエンドにサインアップフォームがあるとしましょう。あなたはそれを記入していて、どこかに詳細を保存するようにサーバーに要求しています。

あなたの要求からユーザー名とパスワードを抽出することはあなたがbody-parserを使うならば以下のように簡単になります。

…………………………………………………。

var loginDetails = {

username : request.body.username,

password : request.body.password

};
0
Rubin bhandari

このようなフォームフィールド

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

上記の回答のいくつかはフラットデータしかサポートしていないため失敗するでしょう。

今のところ私はCasey Chuの答えを使っていますが、 "querystring"モジュールの代わりに "qs" を使います。これが "body-parser" モジュールです。そのため、データを入れ子にしたい場合は、qsをインストールする必要があります。

npm install qs --save

次に、最初の行を次のように置き換えます。

//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

POSTサイズを制限すると、ノードアプリの洪水を防ぐことができます。 expressとconnectの両方に適した素晴らしい raw-body モジュールがあります。これはリクエストをサイズと長さで制限するのに役立ちます。

0
EricSonaron