Error while Uploading a file using FormData Ajax Django - python-3.x

I have been trying to load a multiple file HTML input using Ajax and Django, I know that there are a bunch of questions related to this problem here in StackOverflow but none of the methods have worked for me. I am trying to use a single web page. I would appreciate any recommendation:
HTML Code: This code is inserted also with a click function using ajax, that is why there are a lot of + symbols and everything is inside quotation marks
+'<form id="reclamo" action="{% url "denuncia" %}" method="post" enctype="multiport/form-data">'
+'{% csrf_token %}'+'<label for="files">Adjuntos:</label>'+'<b> </b>'
+'<input type="file" id="files" name="files" multiple><br><br>'
+'<input type="submit" name="upload" value="Reportar">'
+"</form>"
And this one is the Ajax code:
$(document).on('submit','#reclamo',function(e) {
e.preventDefault();
var frm = new FormData($('#reclamo').get(0));
$.ajax({
url: "/denuncia/",
type: "POST",
data: frm,
cache:false,
proccessData: false,
contentType: false,
headers:{
'X-CSRFToken':'{{csrf_token}}'
},
success: function(result){
if (result == 'saved') {
alert('ha sido creada con exito')
}
}
});
})
The error I am getting is:
Uncaught TypeError: Illegal invocation
at e (jquery-3.1.1.min.js:4)
at xb (jquery-3.1.1.min.js:4)
at Function.r.param (jquery-3.1.1.min.js:4)
at Function.ajax (jquery-3.1.1.min.js:4)
at HTMLFormElement.<anonymous> ((index):226)
at HTMLDocument.dispatch (jquery-3.1.1.min.js:3)
at HTMLDocument.q.handle (jquery-3.1.1.min.js:3)

Looks like your data attribute is misspelled. Not sure if this solves it, just saw it. Try edit it to formData.

Related

req.body value undefined for form field value set by javascript function

I am building a node.js,express.js and passport.js app. Once logged into the profile I ask the user to click a button “Get Location” to get the users location.
Profile.ejs
<form action="/testform" method="post" >
<div class="form-group">
<input type="text" class="form-control" id="latVal" placeholder="latitude">
<input type="text" class="form-control" id="longVal" placeholder="longitude">
</div>
<button type = "submit" class="btn btn-warning btn-sm">Save</button>
</form>
<button type = "submit" class="btn btn-warning btn-sm" onclick="getLocation()">Get Location</button>
onclick the getLocation() function is called which is located in mapCall.js
function getLocation()
…
//call to showLocation()
}
function showLocation(position) {
…
document.getElementById("latVal").value = latitude;
document.getElementById("longVal").value = longitude;
}
showLocation() sets the values in the form to the latitude (id="latVal") and longitude (id="longVal") returned from the API call. The values appear in the form field. From here I want to save these values to the users profile data in MongoDB which I try to achieve in routes.js by click of the “Save” button which triggers the function below
app.post('/testform', isLoggedIn, function(req, res) {
user.findById(req.user.id, function(err,user) {
if(!user) {
req.flash('error', 'No accound found');
return res.redirect('/profile');
}
user.location.latitude = req.body.latVal;
user.location.longitude = req.body.longVal;
user.save(function(err){
res.redirect('/profile');
});
});
});
When I console.log req.body.latVal and req.body.longVal the value for these variables is undefined. Nothing is saved in the db.
In server.js I have
var bodyParser = require('body-parser');
app.use(bodyParser());
Upon looking into proposed solutions to req.body returning undefined I tried
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
I didn’t think adding the two lines above would work because the value returned by the API is not in JSON format. This did not work. I checked the typeof for latitude and longitude and it is a number. I am not sure why req.body is not picking up the value.
My initial guess was that app.post tries to read the value before the API can return a value in which case req.body.latVal would read an empty field. I added the save button to test that theory which also proved wrong.
The closest thing I found to my issue is this which was never resolved.
Any guidance is highly appreciated or perhaps even a better way to accomplish this will be great. The reason I have the form fields populate is because I couldn't think of another way to send the values from the frontend to the backend for saving.
Add the name attribute to your inputs.
<input type="text" class="form-control" id="latVal" placeholder="latitude" name="latVal">
<input type="text" class="form-control" id="longVal" placeholder="longitude" name="longVal">
EDIT: (from the comment)
You can do an AJAX call to your server after the getLocation() call.
function getLocation() {
///you get the lat and long
showLocation(position)
saveLocation(latitude, longitude)
.then(function(resp){
//do something with resp
})
}
function saveLocation(latitude, longitude) {
//we have native fetch in newer browsers, so
return fetch("/testform", {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8", //if this doesn't work use the below one
// "Content-Type": "application/x-www-form-urlencoded",
},
body: JSON.stringify({latitude,longitude}), // body data type must match "Content-Type" header
})
.then(response => response.json());
}
This is just an outline of what you can do. Extend this code to your needs.
You are correct in most parts ,You just have to replace ID with name.that is the only way nodejs will be able to locate to your input field

NodeJS Post request using a Button

I don't know if this is possible or not. All the research I've done has shown that it is possible with a form and text input. But anyways, Using NodeJs & Express I want to be able to click a button on my webpage, and once it's clicked, it sends a post request to my Node.JS server.
Simpler way of saying it:
When button is clicked, send info to the server.
Goal I'm trying to achieve:
When button is clicked, it sends some sort of ID/code/anything to turn on a service from my database. (I have yet to learn how db's work so I am just trying to focus on front end.)
Code I have so far:
app.post("/send", function(req, res){
var newID = req.body.ID;
res.redirect("/action")
});
<form action="/send" method="POST">
<input type="button" name="newID" placeholder="Button">
<button>send</button>
</form>
You do not need to use jQuery or AJAX.
Simply add an input of type submit inside the form tag so that the POST request defined by your form tag is submitted.
Your newID input should be of type text, this allows entering a value in the input field.
The newID value can be retrieved server side with req.body.newID (be sure to use the body-parser middleware).
<form action="/send" method="POST">
<input type="text" name="newID" placeholder="Enter your ID"/>
<input type="submit" value="Click here to submit the form"/>
</form>
For this purposes you should use $.ajax,
example:
$('button').on('click', function() {
$.ajax({
type: 'POST',
url: '/send',
data: { ID: 'someid' },
success: function(resultData) {
alert(resultData);
}
});
});

Upload a file with ServiceStack ss-utils.js

I have a job application form as part of a site built on ServiceStack. I am attempting to use the included ss-utils.js to leverage built-in Fluent Validation, but my form doesn't post the user's file upload. Here's the relevant snippet of the form:
<form id="form-careerapplication" action="#(new CreateCareerApplication().ToPostUrl())" method="post">
<div class="error-summary"></div>
<div class="form-group">
<label>
Upload Resume
</label>
<input type="file" id="Resume" name="Resume" />
<span class="help-block"></span>
</div>
<input type="hidden" name="Id" value="#Model.Id" />
<input type="submit" value="Submit Application" />
</form>
<div id="success" class="hidden">
Thank you for your application.
</div>
$("#form-careerapplication").bindForm({
success: function (careerApplicationResponse) {
$("#form-careerapplication").addClass("hidden");
$("#success").removeClass("hidden");
},
...
Is there something I'm missing in ss-utils.js? Or is there a way of overriding / supplementing the submit behavior to use FormData?
Uploading files via a HTML FORM requires a enctype="multipart/form-data", e.g:
<form id="form-careerapplication" action="#(new CreateCareerApplication().ToPostUrl())"
method="post" enctype="multipart/form-data">
...
</form>
If you want to change support multiple file uploads or change the appearance of the UI Form I recommend the Fine Uploader, there's an example showing how to use Fine Uploader on the HTTP Benchmarks Example.
Whilst Imgur has a simple client HTML and Server example.
Turned out I can use the beforeSend option as part of the configuration passed into bindForm to override the data being sent. Its a bit of a hack, but it worked and I keep the original ss-utils.js fluent validation!
$("#form-careerapplication").bindForm({
success: function (careerApplicationResponse) {
....
},
error: function (error) {
....
},
contentType: false,
processData: false,
beforeSend: function (x, settings) {
var fd = new FormData();
// Tweaked library from https://github.com/kflorence/jquery-deserialize/blob/master/src/jquery.deserialize.js
// Used to translate the serialized form data back into
// key-value pairs acceptable by `FormData`
var data = $.fn.deserialize(settings.data);
$.each(data, function (i, item) {
fd.append(item.name, item.value);
});
var files = $('#form-careerapplication').find("input:file");
$.each(files, function (i, file) {
fd.append('file', file.files[0], file.files[0].name);
});
settings.data = fd;
}
});

Data validation in server by socket.io and node.js then POST a from

I have a form like this:
<form method='post' action='next' onsubmit="return validateMyForm();" >
<input type="text" id="data" />
<input type="submit" />
<p id="result"></p>
and this code for interact with node.js:
socket = io.connect();
function vlidateMyForm(){
var data = $('data').val();
socket.emit('login',{data: data}); // check dataBase in server
return false;
}
socket.on('responseLogin',function(result){
if(result){ // if data is valid
// submit form
}
else{ // data invalid
$('#result').html('field is not valid')
}
});
I want to submit my form, when the result is true. What should I do to solve this problem?
Change socket.on('responseLogin',function(result){... to socket.on('login',function(result){... should fix your problem
You can use Jquery submit to submit the form :
$("form#formID").submit();
Your form must have action attribute like action='url_to_post_to' for this.
Or if you like to use AJAX so that you can process the data, you can do :
$.ajax({
type: "POST",
url: 'url_to_post_to',
data: $("#formID").serialize(),
success: function(data)
{
alert(data);
}
});

backbonejs node file upload

None of the answers I have found anywhere have worked. I am trying to extend the example in "Developing Backbone.js Applications" to upload files. Although the form has enctype="multipart/form-data," request.files is always undefined.
The form HTML is:
<form id="addBook" action="..." enctype="multipart/form-data">
<div>
<label for="coverImage">CoverImage: </label><input id="coverImage" name="coverImage" type="file" />
<label for="title">Title: </label><input id="title" type="text" />
<label for="author">Author: </label><input id="author" type="text" />
<label for="releaseDate">Release date: </label><input id="releaseDate" type="text" />
<label for="keywords">Keywords: </label><input id="keywords" type="text" />
<button id="add">Add</button>
</div>
</form>
The backbone that saves the new record is
addBook: function( e ) {
e.preventDefault();
var formData = {};
var reader = new FileReader();
$( '#addBook div' ).children( 'input' ).each( function( i, el ) {
if( $( el ).val() != '' )
{
if( el.id === 'keywords' ) {
formData[ el.id ] = [];
_.each( $( el ).val().split( ' ' ), function( keyword ) {
formData[ el.id ].push({ 'keyword': keyword });
});
} else if( el.id === 'releaseDate' ) {
formData[ el.id ] = $( '#releaseDate' ).datepicker( 'getDate' ).getTime();
} else {
formData[ el.id ] = $( el ).val();
}
}
});
console.log(formData);
this.collection.create( formData );
}
The Node being called.
//Insert a new book
app.post( '/api/books', function( request, response ) {
console.log(request.body);
console.log(request.files);
});
The value of coverimage send to node is correct, I just never get anything in request.files. I have a cool drag and drop I would like to use instead, but until I get this working I am stuck.
I tried the JQuery-file-upload, that got me nowhere.
If I had hair, I would be pulling it out right now.
I wouldn't be submitting the file as part of the model.save/collection.create(model).
What I've used is Plupload for a file upload manager, submitting a file to an upload handler. This upload handler either returns the path to the uploaded file, or fileId if a reference is stored in a database table.
From there I populate a property in my backbone model, then persist the model. You can have your model listenTo plupload, for an upload completed event or similar.
I'm also following the sample of the book "Developing Backbone.js Applications", I extended the functionality to upload images to a folder in the server and save the path in my model to show the correct images. It is working fine. I tried to use Plupload and other jquery plugins but I didn't like them. My sample is using ajax to upload images to the server and then using them. I read many posts referencing the use of iframes to have ajax functionality. The best approach for this I found is using the jquery.form.js to avoid postbacks and load the images in a nice way.
The running sample working fine with nodeJS:
https://github.com/albertomontellano/bookLibrarySampleNodeJS
I based my solution in the post of Mark Dawson:
http://markdawson.tumblr.com/post/18359176420/asynchronous-file-uploading-using-express-and-node-js
However, I had to correct a method of this post to make it work correctly:
app.post('/api/photos', function(req, res) {
var responseServerPath = 'images/' + req.files.userPhoto.name;
var serverPath = 'site/images/' + req.files.userPhoto.name;
console.log(req.files.userPhoto.path);
require('fs').rename(
req.files.userPhoto.path,
serverPath,
function(error) {
if(error) {
console.log(error);
res.send({
error: 'Ah crap! Something bad happened'
});
return;
}
res.send({
path: responseServerPath
});
}
);
});
I hope it helps.
Turned out I had to end up hiring someone to do it, because I can't find any examples online of anybody uploading a file through backbone, even without updating any database interaction. Everybody has the same basic advice about what tools to use to upload the files, but I can't for the life of me find ONE example of someone implementing it.
I am planning on making the code available to everybody, so they can see how it works.

Resources