Bagaimana anda mengekstrak bentuk data (form[method="post"]
) dan upload file yang dikirim dari HTTP POST
metode dalam Node.js?
I'telah membaca dokumentasi, cari di google dan menemukan apa-apa.
function (request, response) {
//request.post????
}
Ada perpustakaan atau hack?
Anda dapat menggunakan querystring
modul:
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.
});
}
}
Sekarang, misalnya, jika anda memiliki sebuah input
field dengan nama usia
, anda bisa mengaksesnya menggunakan variabel post
:
console.log(post.age);
Jika anda menggunakan Express (high-performance, high-kelas pengembangan web untuk Node.js), anda dapat melakukan ini:
HTML:
<form method="post" action="/">
<input type="text" name="user[name]">
<input type="text" name="user[email]">
<input type="submit" value="Submit">
</form>
Klien API:
fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user: {
name: "John",
email: "[email protected]"
}
})
});
Node.js: (sejak 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: (untuk 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)
});
Pastikan untuk membunuh koneksi jika seseorang mencoba untuk banjir RAM anda!
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
});
}
}
Berikut ini's sangat sederhana tanpa framework wrapper berdasarkan jawaban yang lain dan artikel yang diposting di sini:
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();
}
}
Contoh penggunaan:
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);
Banyak dari jawaban berikut yang tidak praktik-praktik yang baik lagi atau don't menjelaskan apa-apa, sehingga's mengapa saya'm menulis ini.
Ketika balik dari http.createServer disebut, adalah ketika server telah benar-benar menerima semua header permintaan, tapi itu's mungkin bahwa data belum diterima, jadi kita harus menunggu untuk itu. The http request objek(http.IncomingMessage contoh) adalah benar-benar dibaca stream. Di readable stream setiap kali sepotong data tiba, sebuah data
acara dipancarkan(dengan asumsi anda telah terdaftar callback untuk itu) dan ketika semua potongan telah tiba sebuah akhir
acara yang dipancarkan. Berikut ini's contoh tentang bagaimana anda mendengarkan acara:
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)
Jika anda mencoba ini, anda akan melihat potongan-potongan yang buffer. Jika anda tidak berurusan dengan data biner dan perlu untuk bekerja dengan string bukannya saya sarankan menggunakan request.setEncoding metode yang menyebabkan aliran memancarkan string ditafsirkan dengan mengingat encoding dan menangani multi-byte karakter dengan benar.
Sekarang anda mungkin tidak tertarik dalam setiap chunk oleh itu's sendiri, jadi dalam hal ini mungkin anda ingin buffer seperti ini:
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)
Di Sini Buffer.concat digunakan, yang hanya merangkai semua buffer dan kembali satu penyangga. Anda juga dapat menggunakan concat-streaming modul yang tidak sama:
const http = require('http');
const concat = require('concat-stream');
http.createServer((request, response) => {
concat(request, data => {
console.log('Data: ', data);
});
}).listen(8080)
Jika anda mencoba untuk menerima bentuk HTML PASCA pengajuan dengan tidak ada file atau menyerahkan jQuery ajax panggilan dengan default tipe konten, maka konten jenis adalah application/x-www-form-urlencoded
dengan uft-8
encoding. Anda dapat menggunakan querystring modul untuk de-cerita bersambung itu dan mengakses properties:
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)
Jika konten anda adalah tipe JSON sebaliknya, anda hanya dapat menggunakan JSON.parse bukan qs.parse.
Jika anda berurusan dengan file atau penanganan multipart jenis konten, maka dalam hal ini, anda harus menggunakan sesuatu seperti yang tangguh yang menghilangkan semua rasa sakit dari berurusan dengan itu. Silahkan lihat di ini jawaban lain saya di mana saya telah diposting link bermanfaat dan modul untuk multipart konten.
Jika anda don't ingin mengurai isi melainkan menyebarkannya ke tempat lain, misalnya mengirim ke yang lain permintaan http sebagai data atau menyimpan ke file saya sarankan piping daripada buffering itu, seperti'll be kode kurang, menangani tekanan balik yang lebih baik, it'll mengambil sedikit memori dan dalam beberapa kasus lebih cepat.
Jadi jika anda ingin menyimpan konten ke file:
http.createServer((request, response) => {
request.pipe(fs.createWriteStream('./request'));
}).listen(8080)
Sebagai jawaban lain telah mencatat menjaga dalam pikiran saya bahwa klien berbahaya mungkin mengirimkan sejumlah besar data crash aplikasi atau mengisi memori anda sehingga untuk melindungi pastikan anda drop permintaan yang memancarkan data yang melewati batas tertentu. Jika anda don't menggunakan perpustakaan untuk menangani data yang masuk. Saya akan menyarankan menggunakan sesuatu seperti stream-meter yang dapat membatalkan permintaan jika mencapai batas yang ditentukan:
limitedStream = request.pipe(meter(1e7));
limitedStream.on('data', ...);
limitedStream.on('end', ...);
atau
request.pipe(meter(1e7)).pipe(createWriteStream(...));
atau
concat(request.pipe(meter(1e7)), ...);
Sementara aku yang dijelaskan di atas pada bagaimana anda dapat menggunakan HTTP request tubuh, hanya untuk buffering dan parsing isi, saya menyarankan menggunakan salah satu dari modul ini agak menerapkan pada anda sendiri karena mereka mungkin akan menangani kasus tepi yang lebih baik. Untuk mengekspresikan saya sarankan menggunakan body-parser. Untuk koa, ada's mirip modul.
Jika anda don't menggunakan framework, tubuh cukup baik.
Itu akan lebih bersih jika anda encode data anda untuk JSON, kemudian mengirimkannya ke 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));
});
}
}
Bagi siapa saja yang bertanya-tanya bagaimana untuk melakukan hal ini sepele tugas tanpa menginstal framework web saya berhasil celepuk ini bersama-sama. Hampir siap produksi tapi tampaknya bekerja.
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);
})
}
}
Anda dapat menggunakan body-parser
, yang Node.js tubuh parsing middleware.
Beban pertama body-parser
$ npm install body-parser --save
Beberapa contoh kode
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);
})
Dokumentasi lebih lanjut dapat ditemukan di sini
Referensi: 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
});
Berikut adalah bagaimana anda bisa melakukannya jika anda menggunakan node-tangguh:
var formidable = require("formidable");
var form = new formidable.IncomingForm();
form.parse(request, function (err, fields) {
console.log(fields.parameter1);
console.log(fields.parameter2);
// ...
});
Jika anda memilih untuk menggunakan murni Node.js maka anda mungkin ekstrak POSTING data seperti ditunjukkan di bawah ini:
// 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}`);
});
Install 'body-parser'
dari npm.
Maka anda aplikasi.ts
var bodyParser = require('body-parser');
app.use(bodyParser.json())
di app.ts modul
app.use(bodyParser.json())
di atas atau sebelum modul deklarasi.
Ex:
app.use(bodyParser.json())
app.use('/user',user);
var postdata = req.body;
Jika anda don't ingin chunk data anda bersama-sama dengan data
callback anda dapat selalu menggunakan dibaca
callback seperti ini:
// 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
});
Pendekatan ini memodifikasi permintaan yang masuk, tetapi segera setelah anda selesai respon permintaan akan menjadi sampah yang dikumpulkan, sehingga seharusnya tidak menjadi masalah.
Lanjutan pendekatan yang akan memeriksa ukuran tubuh pertama, jika anda're takut besar tubuh.
Anda perlu untuk menerima POST
data dalam potongan menggunakan permintaan.pada('data', fungsi(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)
Anda harus mempertimbangkan menambahkan batas ukuran pada bagian yang ditunjukkan posisi sebagai thejh menyarankan.
Ada beberapa cara untuk melakukannya. Namun, cara tercepat yang saya tahu adalah dengan menggunakan Express.js perpustakaan dengan 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);
Yang dapat bekerja untuk string, tapi saya akan mengubah bodyParser.urlencoded untuk bodyParser.json sebaliknya jika POSTING berisi data JSON array.
Info lebih lanjut: http://www.kompulsa.com/how-to-accept-and-parse-post-requests-in-node-js/
Dan jika anda don't ingin menggunakan seluruh kerangka seperti Express, tapi anda juga memerlukan berbagai macam bentuk, termasuk upload, kemudian engkau berjanji mungkin menjadi pilihan yang baik.
Hal ini tercantum dalam Node.js modul
Saya menemukan sebuah video yang menjelaskan tentang cara untuk mencapai hal ini:
Menggunakan default "http" modul bersama-sama dengan "querystring" dan "stringbuilder" modul. Aplikasi ini mengambil dua angka (menggunakan dua kotak teks) dari suatu halaman web dan setelah submit, kembali jumlah dari dua (bersama dengan bertahan pada nilai-nilai di textbox). Ini adalah contoh terbaik yang bisa saya temukan di tempat lain.
Terkait source code:
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);
Bagi mereka yang menggunakan raw binary POSTING tanggal tanpa encoding overhead yang dapat anda gunakan:
klien:
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!");
});
});