Getting 400 Bad Request error when sending form data Angular - angularjs

I am getting a 400 Error when sending a form data to my node.js backend. It also gives me this error: Unexpected token - in JSON at position 0 I know that it isn't a problem with my node app because I can send the same data using Postman and it works perfectly.
This is my Angular method:
const formData = new FormData();
formData.append("db", $scope.item.db.toLowerCase());
formData.append(
"collection",
$("#collection")
.find("option:selected")
.text()
.toLowerCase()
);
formData.append("owner", JSON.parse(sessionStorage.getItem("user"))._id);
formData.append("name", $scope.item.name);
formData.append("description", $scope.item.description);
formData.append("year", $scope.item.year);
formData.append("photo", $("#picture")[0].files[0]);
$http.post("items/uploadItem", formData).then(function(response) {
console.log(response.data);
});
};
If you need any more information, please leave a comment and I would be happy to provide it.

The Angular $http service is expecting standard objects, not a form object. You are sending a serialised form object to your end point. Try
const formData = {
db: $scope.item.db.toLowerCase(),
// and the rest of your object properties.
};

It turns out that I was still sending the data as a json doc. The trick was to change the http call to this:
$http.post("items/uploadItem", formData, {headers: { "Content-Type": undefined }})

Related

Axios POST request

I am trying to send some data from a form to a database using Axios. Here is the code:
const handleSubmit = async () => {
try {
const response = await axios.post(
ApiUrl,
{
batchId,
name,
description,
source,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
console.log(response.data);
handleModal();
} catch (error) {
console.error(error.response.data);
}
};
The error I get is this:
AxiosError {message: 'Request failed with status code 500', name: 'AxiosError', code: 'ERR_BAD_RESPONSE', config: {…}, request: XMLHttpRequest, …}
The values are being stored with useState. The database is receiving inputs but with no data.
I was investigating and I think I need to convert the JSON data to string, but I am not sure how to do that for my code.
If the database is receiving inputs but with no data, it sounds like the API endpoint is being hit properly but you are either improperly extracting the data from (Express?) or improperly passing the extracted values through to whatever function stores them in the database.
You do not need to stringify your axios.post payload.
If you're using Express, make sure you're properly extracting the data from req.body in your endpoint handler. If you're using req.params or req.query that would be a problem.
I would set up some console.log('###') markers in your backend code to ensure the data is reaching the query insertion point.
If you are still having issues, please provide more context regarding your backend logic and the trail between your API and the Database.
I hope this helps!

Axios in React app. Posting image with form data sends request with empty body

I'm trying to send image file to my backend API. Last works fine with Postman. The problem is not with image, I'm not able to send any request with axios and form data, no meter I append image or not.
Everything works fine with fetch. It took time to understand, that fetch does not need any content type, and last generates automatically as multipart/form-data with right boundary.
As written axios should do same as fetch, but it does not generate or change its content-type. Passing header 'content-type' : 'multipart/form-data does not do the trick of course. When I do not set content type it just use application/json. I was not able to find anything like that in documentation. Everywhere its says, that axios should create content type header automatically.
My axios version is 0.18.0.
Here is code, it can't be more simple =)
axios
.post(url, payload)
#######UPDATE#######
It turned out the problem was with axios interceptor. If you don't use interceptors you won't get this problem. So when I created new instance and deleted all headers no interceptors where called that's why my code worked. But let me bring more details to help others avoid this pain. Interceptor has transformRequest function where this part of code exists
if (utils.isObject(data)) {
setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
return JSON.stringify(data);
}
where setContentTypeIfUnset function is
function setContentTypeIfUnset(headers, value) {
if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
headers['Content-Type'] = value;
}
}
So if your object has undefined headers you will also pass this situation. But in my case even after deleting all headers I must pass some header to my application. And on setting it interceptor calls that transfromRequest function which adds that header to my formdata request.
I hope in future releases axios will fix this issue.
#######OLD ANSWER#######
As I guessed, somehow axios in my project set its default value for header content type and even setting it as 'content-type' : undefined did not overwrite that value.
Here is solution
let axiosInstance = axios.create();
delete axiosInstance.defaults.headers;
Then use that instance.
Spent whole day to find this solution.
const formData = new FormData();
formData.append('image', image); // your image file
formData.append('description','this is optional description');
Axios.post(`your url`, {body:formData}, {
headers: {
'content-type': 'multipart/form-data'
}
})
Can you please try this code once ?
You can try like this:
axios({
method: 'post',
url: 'myurl',
data: bodyFormData,
headers: {'Content-Type': 'multipart/form-data' }
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});

Not able to get form-data sent from angular to node server

I am sending form-data along with image-data.
But I am unable to get data on the node server when sent inside FormData.
I could see data on the angular controller on console.log.
angular code:
$scope.saveInfo = function(){
var formData = new FormData;
console.log('Update function');
for(key in $scope.seller){
formData.append(key, $scope.seller[key]);
}
console.log(key, $scope.seller);
var file = $('#file')[0].files[0];
formData.append('image', file);
$http.put('/api/seller/businessInformation', formData, {
transformRequest: angular.Identity,
headers: {
'Content-type': undefined
}
}).then(function(res){
});
}
Node.Js:
I could see image data on console.log(req.files);,
but console.log(req.body); prints [object object].
The best way to tackle this issue is
(i) JSON.stirngify(req.body) in your code.
(ii) See what is the data getting printed, then based on the output you can use req.body.whateverField
EDIT
You can access FormData as,
console.log(req.files.file.name);
and to access FormData you can use
var a = JSON.parse(req.body.name);
console.log(a);
req.body is an object. If your form-data contains name and age. then you can get those values in node like below
req.body.name
req.body.age
The problem is with the ng-model data binding.
I was binding data like this: 'seller.a.b.c'
Instead I did seller.a and it worked.

Angular bad data while trying to post http

I try to send some data (from a form) via $http to my backend. But I'm getting $http:baddata error when I try to send the data.
The full error is "Data must be a valid JSON object" but in my opinion, it is a valid object!
https://docs.angularjs.org/error/$http/baddata?p0=%3Cbr%20%2F%3E%0A%3Cb%3ENotice%3C%2Fb%3E:%20%20Undefined%20index:%20formData%20in%20%3Cb%3EC:%5Cxampp%5Chtdocs%5Cuno-form%5Capi%5Ccontrollers%5CFormController.php%3C%2Fb%3E%20on%20line%20%3Cb%3E26%3C%2Fb%3E%3Cbr%20%2F%3E%0A%7B%22success%22:true,%22data%22:%7B%22form%22:null%7D%7D&p1=%7B%7D
This is the code, and the console.log() result
$scope.submitForm = function(){
console.log("submitForm");
console.log($scope.formData, angular.toJson($scope.formData));
var data = {
formData: angular.toJson($scope.formData)
}
var config = {
headers : {
'Content-Type': 'application/json'
}
}
$http.post('/api/save-form', data,config)
.then(function(response){
console.log("RESPONSE", response);
},function(reason){
console.log("Err");
console.error(reason);
})
}
Console.log:
submitForm
home.controller.js:47 {firstName: "Test"} "{"firstName":"Test"}"
home.controller.js:63 Err
home.controller.js:64 Error: [$http:baddata] (...)
Model in frontend ({{formData}})
{
"firstName": "Test"
}
I have some other way's to send the data, without config, with the other $http way ($http({method: 'POST',....}) but no luck.
What I'm doing wrong here? I have created many forms and functions like this, but I never get this error...
This error can also happen when there is bad data coming from your backend, check if your response is valid.

How to set request part for POST request with angular-file-upload and Spring?

Unfortunately this answer does not help me. The problem appears to be that the request parameter file is not present in my POST request for some reason.
I am trying to upload a file, any file whether it's a binary file or a text file, in a POST request. The REST controller reveals:
#PostMapping(WordEmbeddingApiPaths.UPLOAD_MODEL)
#RequestMapping(method=RequestMethod.POST, headers={"Content-Type=multipart/form-data"})
public ResponseEntity<WordVectorListDto> uploadModel(
#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
LOGGER.debug("POST uploadModel");
return new ResponseEntity<WordVectorListDto>((WordVectorListDto)null, HttpStatus.OK);
}
and on the client I am running:
var uploader = $scope.uploader = new FileUploader({
url: 'http://localhost:8080/rest-api/dl4j/we/uploadModel'
});
uploader.onAfterAddingFile = function($modelFile) {
console.info('onAfterAddingFile', $modelFile);
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
'Content-Type': 'multipart/form-data'
},
params: {'file' : $modelFile.file}
})
.then(
function (data) {
alert("upload success");
},
function (data, status) {
alert("upload error");
}
);
};
However, I am getting 400 Bad Request as server response.
Any idea what the problem is?
Update:
I saw that an internal exception got thrown on the server side stating:
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
I thought that I am setting this already - how can I make this right?
Posting FormData with AngularJS
When doing a POST with a FormData API object, it is important to set the Content-Type header to undefined.
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
//'Content-Type': 'multipart/form-data'
'Content-Type': undefined
},
//params: {'file' : $modelFile.file}
})
When the XHR send() method gets a FormData object created by the FormData API it automatically sets the content type to multipart/form-data and includes the proper boundary.
By having the AngularJS framework override the content type, the boundary is not set properly.
Debugging Small Programs
This question is an example of putting several things together without debugging each part.
This question has several unknown code components:
An undebugged AngularJS POST method
An undebugged Spring Backend
An undebugged mysterious AngularJS service
This answer pointed out errors with the AngularJS POST method but there are a couple of other unknowns. Is the Spring backend working properly? Is the mysterious FileUploader service being used correctly?
Debugging involves isolating unknowns and testing them separately.
Does the Angular POST method work with a known backend such as HTTP BIN - HTTP Request & Response Service?
Does the Spring backend work with an uploader that has been tested?
For more information, see How to debug small programs.
if you are using #EnableAutoConfiguration then you need to do the following as discussed here https://github.com/spring-projects/spring-boot/issues/2958
#EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
define the following beans
#Bean(name = "multipartResolver")
public CommonsMultipartResolver commonsMultipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(50*1024*1024);
return resolver ;
}
#Bean
#Order(0)
public MultipartFilter multipartFilter(){
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}

Resources