Odpowiedzi:
Jeśli korzystasz z Express (wysokowydajne, wysokiej klasy projektowanie stron internetowych dla Node.js), możesz to zrobić:
HTML:
<form method="post" action="/">
<input type="text" name="user[name]">
<input type="text" name="user[email]">
<input type="submit" value="Submit">
</form>
Klient API:
fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user: {
name: "John",
email: "john@example.com"
}
})
});
Node.js: (od 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: (dla 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)
});
app.use(express.bodyParser());
.
Możesz użyć querystring
modułu:
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.
});
}
}
Teraz, na przykład, jeśli masz input
pole o nazwie age
, możesz uzyskać do niego dostęp za pomocą zmiennej post
:
console.log(post.age);
var POST = qs.parse(body); // use POST
tylko dla noobów takich jak ja: gdy nazwa wejściowego pola tekstowego to „użytkownik”, Post.user
pokaże dane tego pola. np.console.log(Post.user);
readable
wywołania zwrotnego zamiast budować dane w ciągu znaków. Po wystrzeleniu ciało jest dostępne przezrequest.read();
req.connection.destroy();
to nie zapobiega wykonaniu wywołań zwrotnych! Na przykład wywołanie zwrotne „on end” zostanie wykonane przy obciętym ciele! Prawdopodobnie nie tego chcesz ...
Pamiętaj, aby zabić połączenie, jeśli ktoś spróbuje zalać pamięć 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
});
}
}
var POST = qs.parse(body); // use POST
tylko dla noobów: gdy nazwa wejściowego pola tekstowego to „użytkownik”, Post.user wyświetli dane tego pola. np. console.log (Post.user);
Wiele odpowiedzi tutaj nie jest już dobrymi praktykami lub niczego nie wyjaśniam, dlatego to piszę.
Kiedy wywołanie zwrotne http.createServer jest wywoływane, oznacza to, że serwer faktycznie otrzymał wszystkie nagłówki żądania, ale możliwe jest, że dane nie zostały jeszcze odebrane, więc musimy na to poczekać. Obiekt żądania HTTP (instancja http.IncomingMessage) jest w rzeczywistości strumieniem czytelnym . W strumieniach czytelnych za każdym razem, gdy przybywa fragment danych, emitowane jest zdarzenie (zakładając, że zarejestrowałeś wywołanie zwrotne do niego), a po nadejściu wszystkich fragmentów wydarzenie jest emitowane. Oto przykład, w jaki sposób słuchasz wydarzeń: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)
Jeśli spróbujesz tego, zauważysz, że fragmenty są buforami . Jeśli nie masz do czynienia z danymi binarnymi i zamiast tego potrzebujesz pracy z ciągami, sugeruję użycie metody request.setEncoding , która powoduje, że strumień emituje ciągi interpretowane z danym kodowaniem i poprawnie obsługuje znaki wielobajtowe.
Teraz prawdopodobnie nie interesuje Cię każdy fragment, więc w tym przypadku prawdopodobnie chcesz go buforować w następujący sposób:
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)
Tutaj używany jest Buffer.concat , który po prostu łączy wszystkie bufory i zwraca jeden duży bufor. Możesz także użyć modułu konkat-stream który robi to samo:
const http = require('http');
const concat = require('concat-stream');
http.createServer((request, response) => {
concat(request, data => {
console.log('Data: ', data);
});
}).listen(8080)
Jeśli próbujesz zaakceptować HTML tworzy przedstawienie POST bez plików lub wręczać jQuery ajax połączeń z domyślnego typu zawartości, a następnie typ zawartości jest application/x-www-form-urlencoded
z uft-8
kodowaniem. Możesz użyć modułu querystring, aby dokonać serializacji i uzyskać dostęp do właściwości:
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)
Jeśli zamiast tego masz typ JSON, możesz po prostu użyć JSON.parse zamiast qs.parse .
Jeśli masz do czynienia z plikami lub obsługujesz wieloczęściowy typ zawartości, to w takim przypadku powinieneś użyć czegoś takiego jak budzący grozę, który usuwa cały ból związany z radzeniem sobie z tym. Spójrz na moją inną odpowiedź, w której zamieściłem pomocne linki i moduły do treści wieloczęściowych.
Jeśli nie chcesz analizować zawartości, ale przesłać ją w inne miejsce, na przykład wyślij ją do innego żądania http jako dane lub zapisz w pliku, sugeruję potokowanie raczej przesłanie zamiast buforowania, ponieważ będzie mniej kod, lepiej radzi sobie z przeciwciśnieniem, zajmie mniej pamięci, a w niektórych przypadkach szybciej.
Więc jeśli chcesz zapisać zawartość do pliku:
http.createServer((request, response) => {
request.pipe(fs.createWriteStream('./request'));
}).listen(8080)
Jak zauważyły inne odpowiedzi, pamiętaj, że złośliwi klienci mogą wysyłać ci ogromną ilość danych, aby spowodować awarię aplikacji lub zapełnić pamięć, aby zabezpieczyć się przed odrzuceniem żądań, które emitują dane, przekraczają pewien limit. Jeśli nie używasz biblioteki do obsługi przychodzących danych. Sugerowałbym użycie czegoś w rodzaju miernika strumienia, który może przerwać żądanie, jeśli osiągnie określony limit:
limitedStream = request.pipe(meter(1e7));
limitedStream.on('data', ...);
limitedStream.on('end', ...);
lub
request.pipe(meter(1e7)).pipe(createWriteStream(...));
lub
concat(request.pipe(meter(1e7)), ...);
Chociaż opisałem powyżej, w jaki sposób można używać treści żądania HTTP, do zwykłego buforowania i analizowania zawartości, sugeruję użycie jednego z tych modułów, który jest implementowany samodzielnie, ponieważ prawdopodobnie będą lepiej obsługiwać przypadki brzegowe. W przypadku ekspresu sugeruję użycie parsera ciała . W przypadku koa istnieje podobny moduł .
Jeśli nie używasz frameworka, body jest całkiem dobre.
request
jest ponownie wykorzystywana i request.on('end')
wywoływana wielokrotnie? Jak mogę tego uniknąć?
request.on('end', ...)
będą wywoływane.
Oto bardzo proste opakowanie bez frameworka oparte na innych odpowiedziach i artykułach zamieszczonych tutaj:
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();
}
}
Przykład użycia:
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);
response.post
bardziej logiczne request.post
. Zaktualizowałem post.
Będzie czystsze, jeśli zakodujesz swoje dane w JSON , a następnie wyślesz je do 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));
});
}
}
qs.parse()
, JSON.parse()
okazało się, że ciało w coś użyteczny. Przykład:, var post = JSON.parse(body);
a następnie uzyskaj dostęp do danych za pomocą post.fieldname
. (Morał z tej historii, jeśli jesteś zdezorientowany co do tego, co widzisz, nie zapomnij o typeof
!)
request.setEncoding
aby to działało poprawnie, w przeciwnym razie może nie obsługiwać poprawnie znaków innych niż ascii.
Dla każdego, kto zastanawia się, jak wykonać to trywialne zadanie bez instalowania frameworka internetowego, udało mi się to połączyć. Produkcja prawie nie jest gotowa, ale wydaje się, że działa.
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);
})
}
}
Możesz użyć body-parser
oprogramowania pośredniczącego do analizowania treści Node.js.
Pierwsze ładowanie body-parser
$ npm install body-parser --save
Niektóre przykładowy kod
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);
})
Więcej dokumentacji można znaleźć tutaj
Odniesienie: 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
});
Oto, jak możesz to zrobić, jeśli używasz węzła-formidable :
var formidable = require("formidable");
var form = new formidable.IncomingForm();
form.parse(request, function (err, fields) {
console.log(fields.parameter1);
console.log(fields.parameter2);
// ...
});
Jeśli wolisz używać czystego pliku Node.js, możesz wyodrębnić dane POST, tak jak pokazano poniżej:
// 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}`);
});
1) Zainstaluj 'body-parser'
z npm.
2) Następnie w pliku app.ts
var bodyParser = require('body-parser');
3) następnie musisz napisać
app.use(bodyParser.json())
w module app.ts
4) pamiętaj, że to Ty
app.use(bodyParser.json())
na górze lub przed jakąkolwiek deklaracją modułu.
Dawny:
app.use(bodyParser.json())
app.use('/user',user);
5) Następnie użyj
var postdata = req.body;
Jeśli nie chcesz porcji danych razem z data
oddzwanianiem, zawsze możesz użyć readable
oddzwaniania w następujący sposób:
// 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
});
Takie podejście modyfikuje przychodzące żądanie, ale zaraz po zakończeniu odpowiedzi zostanie ono wyrzucone, więc nie powinno to stanowić problemu.
Zaawansowanym podejściem byłoby sprawdzenie najpierw wielkości ciała, jeśli boisz się dużych ciał.
request
jest normalnym strumieniem node.js, więc możesz sprawdzić request.headers
długość ciała i przerwać żądanie, jeśli to konieczne.
Można to zrobić na wiele sposobów. Jednak najszybszym sposobem, jaki znam, jest użycie biblioteki Express.js z body-parserem.
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);
Może to działać w przypadku ciągów, ale zamiast tego zmienię bodyParser.urlencoded na bodyParser.json, jeśli dane POST zawierają tablicę JSON.
Więcej informacji: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/
Musisz odbierać POST
dane w porcjach za pomocą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.toString()
})
req.on('end', () => {
console.log(whole)
res.writeHead(200, 'OK', {'Content-Type': 'text/html'})
res.end('Data received.')
})
}
}).listen(8080)
Należy rozważyć dodanie limitu rozmiaru we wskazanej pozycji, zgodnie z sugestią jh .
setTimeout
, gdy połączenie zakończy połączenie po pewnym czasie, jeśli pełne żądanie nie zostanie odebrane w tym oknie.
Jeśli używasz Express.js , zanim będziesz mógł uzyskać dostęp do req.body, musisz dodać oprogramowanie pośrednie bodyParser:
app.use(express.bodyParser());
Następnie możesz poprosić o
req.body.user
A jeśli nie chcesz korzystać z całego frameworka, takiego jak Express, ale potrzebujesz także różnego rodzaju formularzy, w tym przesyłania, formala może być dobrym wyborem.
Jest wymieniony w modułach Node.js
Znalazłem film, który wyjaśnia, jak to osiągnąć: https://www.youtube.com/watch?v=nuw48-u3Yrg
Wykorzystuje domyślny moduł „http” wraz z modułami „querystring” i „stringbuilder”. Aplikacja pobiera dwie liczby (używając dwóch pól tekstowych) ze strony internetowej i po przesłaniu zwraca sumę tych dwóch (wraz z utrwaleniem wartości w polach tekstowych). To najlepszy przykład, jaki mogłem znaleźć gdziekolwiek indziej.
Powiązany kod źródłowy:
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);
Dla tych, którzy używają surowego binarnego przesyłania POST bez narzutu kodowania, możesz użyć:
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);
serwer:
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!");
});
});
Możesz użyć ekspresowego oprogramowania pośredniego, które ma teraz wbudowany parser treści. Oznacza to, że wszystko, co musisz zrobić, to:
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)
})
Ten przykład kodu to ES6 z Express 4.16.x
możesz wyodrębnić parametr post bez użycia express.
1: nmp install multiparty
2: import wielopartyjny. tak jakvar 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: i FORMULARZ HTML JEST.
<form method=POST enctype=multipart/form-data>
<input type=text name=userfile1><br>
<input type=submit>
</form>
Mam nadzieję, że to zadziała dla ciebie. Dzięki.
Ogranicz rozmiar POST, aby uniknąć zalania aplikacji węzła. Istnieje świetny moduł typu raw-body , odpowiedni zarówno do ekspresowego, jak i łączenia, który może pomóc ograniczyć żądanie według rozmiaru i długości.
Jeśli wiąże się to z przesłaniem pliku, przeglądarka zwykle wysyła go jako "multipart/form-data"
typ zawartości. Możesz użyć tego w takich przypadkach
var multipart = require('multipart');
multipart.parse(req)
Na takich polach formularza
<input type="text" name="user[name]" value="MyName">
<input type="text" name="user[email]" value="myemail@somewherefarfar.com">
niektóre z powyższych odpowiedzi zakończą się niepowodzeniem, ponieważ obsługują tylko dane płaskie.
Na razie używam odpowiedzi Casey Chu, ale z „qs” zamiast z modułem „querystring”. Jest to również moduł wykorzystywany przez moduł „body-parser” . Więc jeśli chcesz zagnieżdżonych danych, musisz zainstalować qs.
npm install qs --save
Następnie zastąp pierwszy wiersz, np .:
//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.
});
}
}
Możesz łatwo wysyłać i otrzymywać odpowiedzi na żądanie POST, używając „Żądania - uproszczonego klienta HTTP” i Javascript Promise.
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);
}
});
});
}
Musisz użyć bodyParser (), jeśli chcesz, aby dane formularza były dostępne w req.body. body-parser analizuje twoje zapytanie i konwertuje je do formatu, z którego możesz łatwo wyodrębnić odpowiednie informacje, których możesz potrzebować.
Załóżmy na przykład, że masz interfejs rejestracji w interfejsie użytkownika. Wypełniasz go i prosisz serwer o zapisanie gdzieś szczegółów.
Wyodrębnienie nazwy użytkownika i hasła z żądania jest tak proste, jak poniżej, jeśli używasz parsera ciała.
…………………………………………………….
var loginDetails = {
username : request.body.username,
password : request.body.password
};
JEDEN LINER bez ŚRODKOWEGO OPROGRAMOWANIA
Jeśli publikujesz następujące dane, 'name':'ABC'
możesz je przeanalizować przy użyciu następującego linera ,
require('url').parse(req.url, true).query.name