Попытка отправить данные формы в приложение Express не может правильно проанализировать в req.body

Я знаю, что подобный вопрос задавался много раз, например. здесь.

Однако я безуспешно пробовал применять различные решения из этих ответов.

Вот моя клиентская страница:

<form id="submit_newuser" method="POST" action="/submit_newuser">
    User name:
    <input type="text" id="username" name="username" />
    <br>
    Phone number:
    <input type="text" id="phonenumber" name="phonenumber" />
    <br><br>
    <input type="submit" />
</form>

<script>
document.getElementById("submit_newuser").addEventListener('submit',submit_newuser);

function submit_newuser(event){
    event.preventDefault();
    submit_newuserForm=document.getElementById("submit_newuser");
    formData=new FormData(submit_newuserForm);
    fetch("/submit_newuser",{
        body:formData,
        headers:{
            "Content-Type": "application/json"
        },
        method:"post"
    })
    .then(response=>console.log(response))
    .catch(err=>"submit_newuser: error: "+err);
}
</script>

А вот соответствующий серверный код для конечной точки /submit_newuser:

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

app.post('/submit_newuser',function(req,res){
    console.log("/submit_newuser: req.body: "+JSON.stringify(req.body));
    var phonenumber=req.body.phonenumber;
    var username=req.body.username;
    var output="you submitted: "+username+" "+phonenumber;
    console.log("/submit_newuser: text to send back: "+output);
    res.send(output);
});

При этом, когда я отправляю данные со страницы, сервер регистрирует эту ошибку:

SyntaxError: Unexpected token - in JSON at position 0

Когда я меняю Content-Type на «application/x-www-form-urlencoded», я получаю запись в консоли:

/submit_newuser: req.body: {"------WebKitFormBoundaryBDU4OcntAv7d5wWL\r\nContent-Disposition: form-data; name":"\"username\"\r\n\r\ntestUserName\r\n------WebKitFormBoundaryBDU4OcntAv7d5wWL\r\nContent-Disposition: form-data; name=\"phonenumber\"\r\n\r\ntestPhoneNumber\r\n------WebKitFormBoundaryBDU4OcntAv7d5wWL--\r\n"}

/submit_newuser: text to send back: you submitted: undefined undefined

Это указывает на то, что данные отправляются на сервер, но не анализируются должным образом в req.body.

Решения, связанные с multer, похоже, здесь не применимы, потому что я не загружаю файл, но я не уверен, что мне следует использовать другой подход, чем публикация объекта FormData в теле fetch().

Я в замешательстве, а также интересно, есть ли более простой способ сделать это. Я просто хочу отправлять данные формы на сервер, не вызывая обновления страницы, и иметь возможность обновлять элементы страницы с помощью ответа сервера.


person sigil    schedule 21.08.2019    source источник
comment
Когда вы используете FormData, тип содержимого должен быть multipart/form-data, а не json.   -  person Molda    schedule 21.08.2019


Ответы (3)


Вы можете обновить код на стороне клиента, чтобы отправить тело JSON таким образом, чтобы оно было правильно проанализировано сервером.

Поскольку мы устанавливаем заголовок типа содержимого на JSON на клиенте, мы должны отправлять данные JSON. Мы могли бы отправлять данные в кодировке URL или multipart/form-data, однако для этого нам пришлось бы изменить заголовки на клиенте.

document.getElementById("submit_newuser").addEventListener('submit',submit_newuser);

function formDataToJson(formData) {
    const obj = {};
    formData.forEach((value, key) => { 
        obj[key] = value
    });
    return JSON.stringify(obj);
}

function submit_newuser(event){
    event.preventDefault();
    submit_newuserForm=document.getElementById("submit_newuser");
    formData = new FormData(submit_newuserForm);
    fetch("/submit_newuser",{
        body: formDataToJson(formData),
        headers: {
            "Content-Type": "application/json"
        },
        method:"post"
    })
    .then(response=>console.log(response))
    .catch(err=>"submit_newuser: error: "+err);
}
person Terry Lennox    schedule 21.08.2019

Если вы пытаетесь отправить запрос клиента как formData, вы должны обработать свою серверную часть, чтобы получить запрос как formData.

Существует модуль npm под названием multer для обработки запроса типа formData.

В любом случае ваш код должен измениться на что-то вроде этого:

На стороне клиента

<script>

 document.getElementById("submit_newuser").addEventListener('submit',submit_newuser);

  function submit_newuser(event){
    event.preventDefault();
    submit_newuserForm=document.getElementById("submit_newuser");
    formData=new FormData(submit_newuserForm);
    fetch("http://127.0.0.1:3000/submit_newuser",{
        body:formData,
        method:"post"
    })
    .then(response=>console.log(response))
    .catch(err=>"submit_newuser: error: "+err);
}
</script>

На стороне сервера

const multer = require('multer');
const upload = multer();

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

app.post('/submit_newuser', upload.none(), function (req, res) {
  console.log("/submit_newuser: req.body: " + JSON.stringify(req.body));
  var phonenumber = req.body.phonenumber;
  var username = req.body.username;
  var output = "you submitted: " + username + " " + phonenumber;
  console.log("/submit_newuser: text to send back: " + output);
  res.send(output);
});
person Mosifa    schedule 21.08.2019
comment
Я выбрал подход Терри Ленокса, потому что я могу использовать его без добавления еще одного модуля. Но я буду помнить о вас, если в будущем я решу включить загрузку файлов в отправку формы. - person sigil; 21.08.2019

Используйте приведенный ниже пример вызова ajax для отправки данных из внешнего интерфейса.

var settings = {
  "async": true,
  "crossDomain": true,
  "url": "http://localhost:3000/submit_newuser",
  "method": "POST",
  "data": {
    "username": "test user",
    "phonenumber": "03453512545"
  }
}

$.ajax(settings).done(function (response) {
  console.log(response);
});

образец заявления почтальона.

введите здесь описание изображения

person Mir Nawaz    schedule 21.08.2019