I\'m using jQuery and Ajax for my forms to submit data and files but I\'m not sure how to send both data and files in one form?
I currently do almost the same with b
For me, it didn't work without enctype: 'multipart/form-data'
field in the Ajax request. I hope it helps someone who is stuck in a similar problem.
Even though the enctype
was already set in the form attribute, for some reason, the Ajax request didn't automatically identify the enctype
without explicit declaration (jQuery 3.3.1).
// Tested, this works for me (jQuery 3.3.1)
fileUploadForm.submit(function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: $(this).attr('action'),
enctype: 'multipart/form-data',
data: new FormData(this),
processData: false,
contentType: false,
success: function (data) {
console.log('Thank God it worked!');
}
}
);
});
// enctype field was set in the form but Ajax request didn't set it by default.
<form action="process/file-upload" enctype="multipart/form-data" method="post" >
<input type="file" name="input-file" accept="text/plain" required>
...
</form>
As others mentioned above, please also pay special attention to the contentType
and processData
fields.
In my case I had to make a POST request, which had information sent through the header, and also a file sent using a FormData object.
I made it work using a combination of some of the answers here, so basically what ended up working was having this five lines in my Ajax request:
contentType: "application/octet-stream",
enctype: 'multipart/form-data',
contentType: false,
processData: false,
data: formData,
Where formData was a variable created like this:
var file = document.getElementById('uploadedFile').files[0];
var form = $('form')[0];
var formData = new FormData(form);
formData.append("File", file);
I was having this same issue in ASP.Net MVC with HttpPostedFilebase and instead of using form on Submit I needed to use button on click where I needed to do some stuff and then if all OK the submit form so here is how I got it working
$(".submitbtn").on("click", function(e) {
var form = $("#Form");
// you can't pass Jquery form it has to be javascript form object
var formData = new FormData(form[0]);
//if you only need to upload files then
//Grab the File upload control and append each file manually to FormData
//var files = form.find("#fileupload")[0].files;
//$.each(files, function() {
// var file = $(this);
// formData.append(file[0].name, file[0]);
//});
if ($(form).valid()) {
$.ajax({
type: "POST",
url: $(form).prop("action"),
//dataType: 'json', //not sure but works for me without this
data: formData,
contentType: false, //this is requireded please see answers above
processData: false, //this is requireded please see answers above
//cache: false, //not sure but works for me without this
error : ErrorHandler,
success : successHandler
});
}
});
this will than correctly populate your MVC model, please make sure in your Model, The Property for HttpPostedFileBase[] has the same name as the Name of the input control in html i.e.
<input id="fileupload" type="file" name="UploadedFiles" multiple>
public class MyViewModel
{
public HttpPostedFileBase[] UploadedFiles { get; set; }
}
A Simple but more effective way:
new FormData()
is itself like a container (or a bag). You can put everything attr or file in itself.
The only thing you'll need to append the attribute, file, fileName
eg:
let formData = new FormData()
formData.append('input', input.files[0], input.files[0].name)
and just pass it in AJAX request. Eg:
let formData = new FormData()
var d = $('#fileid')[0].files[0]
formData.append('fileid', d);
formData.append('inputname', value);
$.ajax({
url: '/yourroute',
method: 'POST',
contentType: false,
processData: false,
data: formData,
success: function(res){
console.log('successfully')
},
error: function(){
console.log('error')
}
})
You can append n number of files or data with FormData.
and if you're making AJAX Request from Script.js file to Route file in Node.js beware of using
req.body
to access data (ie text)
req.files
to access file (ie image, video etc)