I'm trying to build a FormData object out of a form on my page. I'm getting the form element like this:
var form = document.forms['upload_form'];
And then I'm building the FormData object like this:
var fd = new FormData(form);
Since you cannot log values in a FormData object (as described here), I'm sending the formdata to '/' just so I can see its contents in my Network Inspector. The contents of the request payload are simply:
------WebKitFormBoundaryKAgAjii8IMLyJFcB--
and nothing else! If I manually append a value to the form like this:
fd.append("username", "Groucho");
it works:
------WebKitFormBoundaryZikgEBo7sTzvlndC
Content-Disposition: form-data; name="username"
Groucho
I've also tried selecting the form element in other ways, such as with jQuery:
var form = $(".upload_form");
var fd = new FormData(form[0]);
No matter how I select the form element, the form variable certainly does have the form in it (it's not null or empty), but constructing the FormData object with it as a parameter just does not seem to work. Can anyone help?
PS I'm using Chrome 31.0.1650.57. I've also tried this in Safari 7.0 with the same results.
Another thing: The inputs in this form are nested inside a number of divs. Could this be a problem?
This was happening because I didn't have name attributes set on my inputs. Apparently, new FormData() and $.serialize() will ignore any inputs without names.
Related
In HTML5 we can use the form attribute on form control elements to have them be part of a form other then the one they're childs of, as described in this answer.
These elements however seem not to be considered when passing the form element to the FormData constructor, as described on MDN.
Is there a way to have these 'external' controls be included in a way that I then can send the complete form data via a fetch Request?
I am aware, that I could loop through the external elements and append them to the FormData instance like so
let formData = new FormData(form);
for (const external of document.body.querySelectorAll('[form="' + form.name + '"]')) {
formData.append(external.name, external.value);
}
However I hoped for a more convenient way, especially taking in consideration the extra cases and checks I would have to make it work with radiobuttons etc.
I'm implementing an ajax form submission that resizes images before submitting them. The javascript basically reads the file as an Image, resizes and draws to canvas, and then appends the data to a FormData object:
var fd = new FormData();
fd.append("image0", canvas.toDataURL("image/png"));
I then do an ajax submission to my django view, verifying with a ModelForm:
forms.py
class InsertProduct(forms.ModelForm):
image0 = forms.ImageField(
required=True,
max_length=64,
widget=forms.FileInput( attrs={"id": "image0",} )
)
views.py
def ajax_upload(request):
if request.method == 'POST':
form = InsertProduct(request.POST, request.FILES)
print(request.POST.urlencode())
print(form.errors)
The urlencode() tells me that I'm receiving the data:
image0=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABE...
But the form errors tells me that I'm not binding it properly:
<ul class="errorlist">
<li>image0<ul class="errorlist"><li>This field is required.</li></ul></li>
</ul>
Maybe the ImageField is looking for the data in request.FILES instead of request.POST? How do I get this working?
So a short answer is to use an image library such as pillow to convert base64 back to an Image file, and manually save.
However, if you can rely on the browser's FormData API, you can do:
var fd = new FormData(document.forms[0]);
var quality = 0.95;
canvas.toBlob(function(blob){
fd.set("image0", blob, "myimage.jpg");
}, "image/jpeg", quality);
Note that Chrome only supports FormData set and append from the latest stable release 50, and my build throws an exception when I try to set a blob. It seems Firefox 46 will do it (set and append are suppored since 44 I think), but only if FormData() is initialised from a DOM <form> element. If you inspect POST you'll find that a file input field (that was not present in the DOM and is appended after) is missing otherwise.
I don't get it, I don't understand.
In a self-developed Python web framework I'm posting a file form element to the server using JavaScript.
var formData = new FormData();
formData.append('file', document.getElementById('file').files[0]);
var request = new XMLHttpRequest();
request.open("POST", url, true);
request.send(formData);
The server, sporting mod_wsgi, receives the request like so:
if environ['REQUEST_METHOD'] == 'POST':
post_env = environ.copy()
post_env['QUERY_STRING'] = ''
form = cgi.FieldStorage(
fp=environ['wsgi.input'],
environ=post_env,
keep_blank_values=True)
Then, when I want to access the form field's content to save it to a file, the following will return an empty result:
form['file'].file.read()
(All code has been edited for simplicity)
What puzzles me is that the form field will show the correct file name and MIME type, only file.read() remains empty.
Also all other information from other input text fields comes through and is accessible.
I also checked that environ['REQUEST_METHOD'] is actually POST.
As to HTTP Headers for encoding (such as multipart/form-data), I thought that the XMLHttpRequest object will take care of that, once formData.append() receives a file input as the value.
Okay, here's the solution:
I can't explain it, but the file form fields get emptied on first read, which I found out by accident. Maybe a bug, who knows.
I assumed that they would stay intact (like any other variable) and can be read multiple times.
What I ignored was that I had in fact addressed them several times.
So the solution was to first store the file's content in a variable, and then use that multiple times.
I want to send the value of a JavaScript variable (variableToSend) to a PHP variable ($latLong) which then gets posted to MySQL. The JavaScript variable is capturing the value of an HTML textbox outside of a form listed below:
<input type="text" id="latLng" value="Working"/>
The textbox value passes to the Javascript variable just fine (I've tested via an alert with the variable's value):
<script language="JavaScript">
setTimeout(function(){
var variableToSend = document.getElementById("latLng").value;
$.post('html/index.php', {$latLong: "variableToSend"});
}, 10000);
</script>
However, the $.post method is not firing. I'm thinking one of a couple of things were happening. One, the text field was not in a form which is why it didn't pass to the PHP variable. I tested this by throwing the text field back in a form tag, but that didn't work. Second, the $.post method is written incorrectly. Third, the $.post method is not firing at all after the 10 second interval. I'm thinking it's the third case but would like some direction if at all possible.
Any help is greatly appreciated.
You can use a QueryString appended to the script. Another better option would be to use the FormData object.
Here is a sample from MDN:
var formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountnum", 123456); // number 123456 is immediately converted to string "123456"
// HTML file input user's choice...
formData.append("userfile", fileInputElement.files[0]);
// JavaScript file-like object...
var content = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var blob = new Blob([content], { type: "text/xml"});
formData.append("webmasterfile", blob);
var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php");
request.send(formData);
This question already has answers here:
How to inspect FormData?
(22 answers)
Closed 6 years ago.
I'm trying to get a set of keys (input names or similar) and values (input values) from a web form:
<body>
<form>
<input type="text" name="banana" value="swag">
</form>
<script>
var form = document.querySelector('form');
var formData = new FormData(form);
</script>
</body>
According to the FormData documentation, formData should contain the keys and values from the form. But console.log(formData) shows formData is empty.
How can I quickly get the data from the form using FormData?
JSFiddle
Update: the XHR spec now includes several more functions to inspect FormData objects.
FireFox has supported the newer functions since v39.0, Chrome is slated to get support in v50. Not sure about other browsers.
var form = document.querySelector('form');
var formData = new FormData(form);
for (var [key, value] of formData.entries()) {
console.log(key, value);
}
//or
console.log(...formData)
I faced the same problem as well. I wasn't able to see on the console. You need to add the following to the ajax request, so the data will be sent
processData: false, contentType: false
But console.log(formData) shows formData is empty.
What do you mean by "empty"? When I test this in Chrome it shows ‣ FormData {append: function} ... which is to say it's a FormData object, which is what we expected. I made a fiddle and expanded to code to this:
var form = document.querySelector('form'),
formData = new FormData(form),
req = new XMLHttpRequest();
req.open("POST", "/echo/html/")
req.send(formData);
...and this is what I saw in the Chrome Developer Tools Network panel:
So the code is working as expected.
I think the disconnect here is that you're expecting FormData to work like a vanilla JavaScript object or array and let you directly look at and manipulate its contents. Unfortunately it doesn't work like that—FormData only has one method in its public API, which is append. Pretty much all you can do with it is create it, append values to it, and pass it to an XMLHttpRequest.
If you want to get the form values in a way you can inspect and manipulate, you'll have to do it the old-fashioned way: by iterating through the input elements and getting each value one-by-one—or by using a function written by someone else, e.g. jQuery's. Here's an SO thread with a few approaches to that: How can I get form data with JavaScript/jQuery?
As per MDN documentation on FormData
An object implementing FormData can directly be used in a for...of structure, instead of entries(): for (var p of myFormData) is equivalent to for (var p of myFormData.entries()).
Iterating over FormData.entries() didn't worked for me.
Here is what I do to check if formData is empty or not:
var isFormDataEmpty= true;
for (var p of formData) {
isFormDataEmpty= false;
break;
}
As iterating over formData gives you the uploaded file, you can use it for getting the file name, file type validation, etc.