Formdata is setting the string "null" to null values

Asked

Viewed 1,213 times

3

I’m using a library called ngUpload. In it we have the option to send the data along with the upload of a particular file.

I’m uploading this as follows:

Upload.upload({
    url: '/orcamento/ajax-criar', 
    data: {cliente: $scope.cliente, orcamento: $scope.orcamento}
})

But when I receive this data on the server, it is being sent as string improperly.

Example:

 var_dump(
  $request->request->get('cliente')['cadastrado']
 ); 

 // Retorna: string(4)'true'

 var_dump(
  $request->request->get('cliente')['telefone']
 ); 

 // Retorna: string(4)'null'

I noticed that this seems to be a problem of FormData.

Example:

f = new FormData;

f.append('null_value', null);
f.append('boolean_value', false);

console.log(f.get('null_value'), typeof f.get('null_value'));

console.log(f.get('boolean_value'), typeof f.get('boolean_value'));

In that case, since the FormData does not make a correct substitution of the values, which is the solution I could apply so that the values are sent correctly?

This is disrupting server-side validation due to the fact that it is sending "null" instead of sending nothing. For example, the telephone field, which has to have the correct format but is not mandatory, if the value is empty, is valid.

1 answer

2


There is no way to send "primitive" values unless you use a format like JSON and decode when you arrive at the server, all that is sent via HTTP will be text or "binary".

Precisely for this reason there are methods like Json, Xml and serialization, to be able to send the data in a standard format which can be interpreted in the back-end or front-end (depends on where to send). So you can do it like this:

var f = new FormData;

data = { "telefone": null, "nome": "Wallace" };

f.append('data', JSON.stringify(data));

//Ainda string
console.log(f.get("data"));

//Decodificado
var parsed = JSON.parse(f.get("data"));

console.log(parsed.nome, parsed.telefone);

And when you get to the back end:

$data = json_decode($request->request->get('cliente')['data']);

var_dump($data);

Or if it’s pure PHP:

$data = json_decode($_POST['data']);

var_dump($data);

Using only strings

Another way would be when NULL simply swap the value for an empty string and when it is false nay add item to FormData, being angular.js I believe I can filter the items before, but since I don’t understand this the basic explanation would be this:

function appendToForm(form, key, value)
{
    if (value === null) { //Null é vazio
       form.append(key, "");
    } else if (value === false || typeof value === "undefined") {//False e undefined é desconsiderado
       form.append(key, value);
    } else if (value === true) { //True vira 1
       form.append(key, "1");
    } else {//Outros valores viram string se necessário
       form.append(key, value);
    }
}

var f = new FormData;

appendToForm(f, "nome", "JBueno ♥ JavaScript");
appendToForm(f, "telefone", null);

for (var k of f.keys()) {
   var value = f.get(k);
   console.log(k, "=>", value, ',tipo =>' + typeof value);
}

I don’t know anything about Angular.js, but I think using the Upload plugin would simply be like this:

function appendToForm(data, key, value)
{
    if (value === null) {
       data[key] = "";
    } else if (value === false || typeof value === "undefined") {
       data[key] = value;
    } else if (value === true) {
       data[key] = "1";
    } else {
       data[key] = value;
    }
}

...

var data = {};

appendToForm('cliente', $scope.cliente);
appendToForm('orcamento', $scope.orcamento);

Upload.upload({
    url: '/orcamento/ajax-criar', 
    data: data
})

XML

If you were to transport via Xml, for example to a Webservice that supports SOAP you could use the attribute xsi:nil (requires the namespace xmlns:xsi="w3.org/2001/XMLSchema-instance"), so for example:

<tag xsi:nil="true" />
<tag xsi:nil="false" />
<tag xsi:nil="null" />

You can also take a look at W3.org, I know it’s getting away from the subject, but it’s just to explain the serialization, in version 1.1 of SOAP (I’m not really sure if it’s something supported) indicates that can use xsd:null="true".

Of course you can create your own Xml and send via Ajax maybe, including even the image data in base64, it will be a little laborious, but it is only for understanding even, for example:

<?xml version="1.0"?>
<upload>
    <item type="bin" name="foto">base64 com o conteudo do upload</item>
    <item type="bool" name="possui_carro">true</item>
    <item type="bool" name="possui_moto">false</item>
    <item type="null" name="telefone" />
    <item name="hello_world">olá, mundo!</item> <!-- para string pode omitir o type ou adicionar type="string" -->
</upload>

And in the back-end you decode and can use Simplexmlelement if it’s php for example, of course you’ll have to do the "parse" manually using the attribute type="" and the content of the tag <item>

  • 1

    Very good! I really had to use this solution. It would be nice if Javascript solved this, since the FormData is their responsibility :p

  • @Wallacemaxters Javascript is language, no matter what you do, FormData is an API and HTTP is a protocol, if the protocol specifies that everything that is passed is text or binary has no way of blaming either Javascript or Formdata for something impossible to achieve, they are following the protocol, you can automate input data and create an interpreter that requires a back-end format, just like SOAP does on servers that use this kind of webservice ;)

  • That is, make an object filter or use JSON.stringify

  • 2

    "PHP pure" - Only if it is pure evil.

  • 3

    @Wallacemaxters Javascript solves a problem and creates another 14 =D

Browser other questions tagged

You are not signed in. Login or sign up in order to post.