Symfony 5 - javascript XMLHttpRequest 发送的表单数据对象未在控制器中提交
Symfony5 - formData object send by javascript XMLHttpRequest not Submited in controller
我正在尝试在 canvas 上保存图像(保存它掉落到的位置、它的来源...等)。为了实现这一点,每个图像都被认为是一个对象,该对象具有一个 saveObject 方法,该方法将 POST 一个 formData 对象向 Symfony5 控制器抛出一个 XMLHttpRequest,它将以 symfony 形式接收 formData。
symfony 表单绑定到表示 canvas 中对象的实体,并且应该在提交时将表单数据内容保存到数据库中。
我面临的问题是控制器似乎没有考虑提交的表单。
我检查过:formData 对象确实包含 XMLHttpRequest 之前的所有数据,但在控制器端,所有字段似乎都设置为 null。
这是 saveObject 方法:
saveObject() {
console.log("In saveObject");
var xhr = new XMLHttpRequest();
var FD = new FormData;
// set FormData values
for (name in this) {
if (name === 'album_id') {
FD.append(name, this.parent_album);
} else {
FD.append(name, this[name])
}
}
//used to check if FD contains the data it is supposed to
for (var key of FD.entries()) {
console.log(key[0] + ', ' + key[1]);
}
xhr.open('POST', '/edit/storeObjects/');
xhr.send(FD);
xhr.onload = function () {
if (xhr.status != 200) {
alert(`Error ${xhr.status}: ${xhr.statusText}`);
} else {
console.log("subission ok");
console.log(xhr.response);
}
}
}
这是接收请求的控制器:
/**
* @Route ("/edit/storeObjects/", name="save_object")
*/
public function saveObj(Request $request, EntityManagerInterface $em, UploaderHelper $uploaderHelper, SluggerInterface $slugger)
{
$albumObj = new AlbumObjects();
$user = $this->getUser();
$form = $this->createForm(SaveObjectFormType::class);
$form->handleRequest($request);
if ($request->isMethod('POST')) {
$form->submit($request->request->get($form->getName()));
if ($form->isSubmitted() && $form->isValid()) {
/** @Var AlbumObjects $albumObj * */
$albumObj = $form->getData();
if (true == $form['destImg']->getData()) {
$destImg = $form['destImg']->getData();
$user_dest = $user->getOwneravatar();
$newFilename = $uploaderHelper->uploadProfilePicture($user_dest, $destImg, $slugger);
$albumObj->setDestImg($newFilename);
}
$em->persist($albumObj);
$em->flush();
return $this->json([
'saveStatus' => 'Saved'
]);
}
}
return $this->json([
'saveStatus' => 'Not saved',
'albumObj' => $albumObj
]);
}
我显然做错了什么,如果能提示我遗漏了什么,我将不胜感激
我大部分都错了,但在朋友的一些建议下,现在可以正常工作了,所以我post告诉她我所做的修改,以防其他人遇到同样的问题.
首先,由于 symfony 表单中包含的 csrf 保护,表单未被验证或提交。
为了解决这个问题,我得到的建议非常有效,而不是将 post 数据发送到表单的普通 xmlhttprequest :首先执行 get 请求,然后从 csrf 表单中获取 return令牌。
然后在 javascript 中创建 formData 对象时,需要将表单的名称属性作为参数。
最后,虽然图像已发送到控制器,但并未在控制器中提交(我还检查了 enctype 是否正确)。我通过直接在 Request 对象中获取图像来解决这个问题。这个解决方案虽然“感觉不对”
这就是我更改 javascript xmlhttprequest 部分的方式:
saveObject() {
let xhr = new XMLHttpRequest();
xhr.open('GET', '/edit/storeObjects/');
xhr.send();
xhr.onload = function () {
if (xhr.status !== 200) {
alert(`Error ${xhr.status}: ${xhr.statusText}`);
} else {
var formName = document.createElement('form');
formName.setAttribute('name', JSON.parse(xhr.response)['formName']);
var fD = new FormData(formName);
var attrListe = ['parentAlbum','pageNumber','type','dx','dy','dwidth','dheight','sx','sy','swidth','sheight','destImg','containedText','fontSize', 'fontType','fontColor','textMaxWidth','textLineHeight','album']
attrListe.forEach(attrName => {
if (attrName == 'destImg') {
var file = this.dataURLtoFile(this.destImg, 'img');
fD.append(attrName, file);
} else {
fD.append(attrName, this[attrName])
}
});
fD.append('_token', JSON.parse(xhr.response)['token']);
for (var value of fD.entries()) {
console.log(value[0] + ': ' + value[1]);
}
let xhrPost = new XMLHttpRequest();
xhrPost.open('POST', '/edit/storeObjects/');
xhrPost.send(fD);
xhrPost.onload = function () {
if (xhrPost.status !== 200) {
alert(`Error ${xhrPost.status}: ${xhrPost.statusText}`);
} else {
console.log("Object Saved")
}
}
}
}.bind(this)
}
这里是对控制器的修改:
public function saveObj(Request $request, EntityManagerInterface $em, UploaderHelper $uploaderHelper, SluggerInterface $slugger)
{
$user = $this->getUser();
$form = $this->createForm(SaveObjectFormType::class);
$form->handleRequest($request);
if ($request->isMethod('POST')) {
$form->submit($request->request->all());
if ($form->isSubmitted() && $form->isValid()) {
/** @Var AlbumObjects $albumObj * */
$albumObj = $form->getData();
//Check if the image field contains a file and if it does process it
if ($request->files->get('destImg')) {
$dest_Img = $request->files->get('destImg');
$user_dest = $user->getOwneravatar();
$newFilename = $uploaderHelper->uploadProfilePicture($user_dest, $dest_Img, $slugger);
$albumObj->setDestImg($newFilename);
}
$em->persist($albumObj);
$em->flush();
return $this->json([
'saveStatus' => 'Saved',
]);
}
}
return $this->json([
'formName' => $form->createView()->vars['name'],
'token' => $form->createView()->children['_token']->vars['value']
]);
}
我正在尝试在 canvas 上保存图像(保存它掉落到的位置、它的来源...等)。为了实现这一点,每个图像都被认为是一个对象,该对象具有一个 saveObject 方法,该方法将 POST 一个 formData 对象向 Symfony5 控制器抛出一个 XMLHttpRequest,它将以 symfony 形式接收 formData。 symfony 表单绑定到表示 canvas 中对象的实体,并且应该在提交时将表单数据内容保存到数据库中。
我面临的问题是控制器似乎没有考虑提交的表单。 我检查过:formData 对象确实包含 XMLHttpRequest 之前的所有数据,但在控制器端,所有字段似乎都设置为 null。
这是 saveObject 方法:
saveObject() {
console.log("In saveObject");
var xhr = new XMLHttpRequest();
var FD = new FormData;
// set FormData values
for (name in this) {
if (name === 'album_id') {
FD.append(name, this.parent_album);
} else {
FD.append(name, this[name])
}
}
//used to check if FD contains the data it is supposed to
for (var key of FD.entries()) {
console.log(key[0] + ', ' + key[1]);
}
xhr.open('POST', '/edit/storeObjects/');
xhr.send(FD);
xhr.onload = function () {
if (xhr.status != 200) {
alert(`Error ${xhr.status}: ${xhr.statusText}`);
} else {
console.log("subission ok");
console.log(xhr.response);
}
}
}
这是接收请求的控制器:
/**
* @Route ("/edit/storeObjects/", name="save_object")
*/
public function saveObj(Request $request, EntityManagerInterface $em, UploaderHelper $uploaderHelper, SluggerInterface $slugger)
{
$albumObj = new AlbumObjects();
$user = $this->getUser();
$form = $this->createForm(SaveObjectFormType::class);
$form->handleRequest($request);
if ($request->isMethod('POST')) {
$form->submit($request->request->get($form->getName()));
if ($form->isSubmitted() && $form->isValid()) {
/** @Var AlbumObjects $albumObj * */
$albumObj = $form->getData();
if (true == $form['destImg']->getData()) {
$destImg = $form['destImg']->getData();
$user_dest = $user->getOwneravatar();
$newFilename = $uploaderHelper->uploadProfilePicture($user_dest, $destImg, $slugger);
$albumObj->setDestImg($newFilename);
}
$em->persist($albumObj);
$em->flush();
return $this->json([
'saveStatus' => 'Saved'
]);
}
}
return $this->json([
'saveStatus' => 'Not saved',
'albumObj' => $albumObj
]);
}
我显然做错了什么,如果能提示我遗漏了什么,我将不胜感激
我大部分都错了,但在朋友的一些建议下,现在可以正常工作了,所以我post告诉她我所做的修改,以防其他人遇到同样的问题.
首先,由于 symfony 表单中包含的 csrf 保护,表单未被验证或提交。 为了解决这个问题,我得到的建议非常有效,而不是将 post 数据发送到表单的普通 xmlhttprequest :首先执行 get 请求,然后从 csrf 表单中获取 return令牌。
然后在 javascript 中创建 formData 对象时,需要将表单的名称属性作为参数。
最后,虽然图像已发送到控制器,但并未在控制器中提交(我还检查了 enctype 是否正确)。我通过直接在 Request 对象中获取图像来解决这个问题。这个解决方案虽然“感觉不对”
这就是我更改 javascript xmlhttprequest 部分的方式:
saveObject() {
let xhr = new XMLHttpRequest();
xhr.open('GET', '/edit/storeObjects/');
xhr.send();
xhr.onload = function () {
if (xhr.status !== 200) {
alert(`Error ${xhr.status}: ${xhr.statusText}`);
} else {
var formName = document.createElement('form');
formName.setAttribute('name', JSON.parse(xhr.response)['formName']);
var fD = new FormData(formName);
var attrListe = ['parentAlbum','pageNumber','type','dx','dy','dwidth','dheight','sx','sy','swidth','sheight','destImg','containedText','fontSize', 'fontType','fontColor','textMaxWidth','textLineHeight','album']
attrListe.forEach(attrName => {
if (attrName == 'destImg') {
var file = this.dataURLtoFile(this.destImg, 'img');
fD.append(attrName, file);
} else {
fD.append(attrName, this[attrName])
}
});
fD.append('_token', JSON.parse(xhr.response)['token']);
for (var value of fD.entries()) {
console.log(value[0] + ': ' + value[1]);
}
let xhrPost = new XMLHttpRequest();
xhrPost.open('POST', '/edit/storeObjects/');
xhrPost.send(fD);
xhrPost.onload = function () {
if (xhrPost.status !== 200) {
alert(`Error ${xhrPost.status}: ${xhrPost.statusText}`);
} else {
console.log("Object Saved")
}
}
}
}.bind(this)
}
这里是对控制器的修改:
public function saveObj(Request $request, EntityManagerInterface $em, UploaderHelper $uploaderHelper, SluggerInterface $slugger)
{
$user = $this->getUser();
$form = $this->createForm(SaveObjectFormType::class);
$form->handleRequest($request);
if ($request->isMethod('POST')) {
$form->submit($request->request->all());
if ($form->isSubmitted() && $form->isValid()) {
/** @Var AlbumObjects $albumObj * */
$albumObj = $form->getData();
//Check if the image field contains a file and if it does process it
if ($request->files->get('destImg')) {
$dest_Img = $request->files->get('destImg');
$user_dest = $user->getOwneravatar();
$newFilename = $uploaderHelper->uploadProfilePicture($user_dest, $dest_Img, $slugger);
$albumObj->setDestImg($newFilename);
}
$em->persist($albumObj);
$em->flush();
return $this->json([
'saveStatus' => 'Saved',
]);
}
}
return $this->json([
'formName' => $form->createView()->vars['name'],
'token' => $form->createView()->children['_token']->vars['value']
]);
}