Jquery: Push FormData? - javascript

Is there a way to add additional data to a formdata element that handles a file upload? I know formdata doesn't support .push()?
$("frm").submit(function (e) {
e.preventDefault();
var data = new FormData($(this)[0]);
});

If I'm understanding your question correctly, you want to add extra keys and values to the FormData object after taking them from the form. If so, yes you can! It uses the append method:
data.append('SomeField', 'SomeValue');
You can do this with a string, or with a Blob or File object as suits you.
This is documented in the MDN page for FormData.

Related

Is there a way to put Express.Multer.File into a FormData object?

I need help on finding how to put a file with a type Express.Multer.File into a FormData object.
Context: I'm receiving a file with a type Express.Multer.File (I'm using nestjs, so I used this part of the documentation : https://docs.nestjs.com/techniques/file-upload) that I need to put in a FormData, to send it to another API.
I tried form.append('randomword', file); but I get the following error :
TypeError: source.on is not a function
at Function.DelayedStream.create (xxx/delayed-stream/lib/delayed_stream.js:33:10)
at FormData.CombinedStream.append (xxx/combined-stream/lib/combined_stream.js:45:37)
...
I clearly sense that I'm doing it the wrong way, but I'm kinda lost on how to achieve something like this.
Could someone help me please ?
You can use buffer and originalname obtained from multer to create a new Form Data.
For example, this would be the solution when you have only one file sent via POST method:
router.post("/", multer().single("file"), async (req, res, next) => {
let data = new FormData();
data.append("yourFormDataKey", req.file.buffer, req.file.originalname)
//HERE GOES YOUR CODE WHERE YOU USE THE FORM DATA CREATED//
}
I found out a "workaround" for this method.
First, I get the file with the type Express.Multer.File.
Then I save it using createWriteStream from fs.
Finally, I pass it into the FormData object using createReadStream.
And done !
It isn't the best way to do this, but kind of a workaround, though.

Does fetch support multiple file upload natively?

Summary
I am trying to set my FormData properly using javascript.
I need to be able to upload jpg/png, but I might need to upload some other file types pdf/csv in the future using fetch.
Expected
I expect it to append the data to the form
Error
Working
This snippet is working fine:
const formData = new FormData(document.querySelector('form'));
formData.append("extraField", "This is some extra data, testing");
return fetch('http://localhost:8080/api/upload/multi', {
method: 'POST',
body: formData,
});
Not working
const formData = new FormData();
const input = document.querySelector('input[type="file"]');
formData.append('files', input.files);
Question
Does fetch support multiple file upload natively?
If you want multiples file, you can use this
var input = document.querySelector('input[type="file"]')
var data = new FormData()
for (const file of input.files) {
data.append('files',file,file.name)
}
fetch('http://localhost:8080/api/upload/multi', {
method: 'POST',
body: data
})
The issue with your code is in the lineformData.append('files', input.files);
Instead of that, you should upload each file running a loop with unique keys, like this
const fileList = document.querySelector('input[type="file"]').files;
for(var i=0;i<fileList.length;i++) {
formData.append('file'+i, fileList.item(i));
}
I have created a simple error fiddle here with your code. You can check its' submitted post data here, where you can see that no file has been uploaded.
At the bottom of the page you can find
.
I have corrected the fiddle here with the fix. You can check its'post data from the server, where it shows the details of the two files that I uploaded.
I mentioned this on a similar question: I had the same problem, but with a PHP backend. The unique formData keys work, but I found that the classic HTML notation worked just fine and simply results in an array on the server.
formData.append('file[]', data[i]);
I like that a lot better, since I can use the same methods to process this as with a classic <input type="file" multiple />.

Submit binary data via Prototype Ajax call

I'm using Prototype to submit a POST request, and the postdata contains a number of fields, one of which is binary data from a file (in this case an Excel spreadsheet the user has selected for upload.)
I am using the HTML5 FileReader interface to get the contents of the file via FileReader.readAsBinaryString() which works well. If I use charCodeAt() to print various characters in the string then they come out with the expected values.
However once I put this string data in an object (along with the other form fields) and pass it as the parameters option to Prototype's Ajax.Request(), the data arrives corrupted. Certain character values like 0x82 are replaced with 0xC2 0x82, 0xAC is replaced with 0xC2 0xAC, and so on.
I tried using window.atob() to base64 encode the string, but this fails with InvalidCharacterError: String contains an invalid character, so clearly there is some kind of processing going on which I need to avoid.
Does anyone know how to pass binary data through Prototype's Ajax.Request() while also including additional form fields in the same request?
To do ajax file upload you should really use a FormData object
var data = new FormData();
//var data = new FormData(someForm); if all your fields is in an html form
// add fields to form
data.append('fieldname',fieldvalue);
data.append('filefieldname',fileobject);
//etc
new Ajax.Request(url, {
contentType: null,
method: 'post',
postBody: data,
onSuccess: successFunction
})
With this method the server will see the request like if it was sent by a form with attribute enctype="multipart/form-data"
Doing this requires magic and pixie dust. (well not really)
firstly you would need to put the form fields values as URL parameters instead of POST and then override the post body with the file contents. For example
new Ajax.Request('/url.php?rawupload=1&id='+$F('id')+'&label='+label,
{
'method':'post',
'postBody':fileobject,
'onSuccess':function() { alert('success'); }
});
fileobject is the HTML5 file object retrieved from the file upload input element
Yes its not the most elegant solution if you have lots of form fields. You can also use Hash#toQueryString if you do have lots of form fields to build your query string instead of doing them by hand
http://api.prototypejs.org/language/Hash/prototype/toQueryString/

FormData created from an existing form seems empty when I log it [duplicate]

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.

Can't build a FormData object out of existing form

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.

Categories

Resources