How to use AngularJS $http to send multipart/form-data - javascript

I am developing a graphical interface that uses different services rest (written in java).
I have to call up a service like this:
#PUT
#Path("nomeServizio")
public Response nomeServizio(final FormDataMultiPart multiPart) {
......}
Call service:
service: function (data) {
return $http({
url: PATH_REST_SERVICES + '/nomeServizio',
headers: {"Content-Type": "multipart/form-data"},
data: data,
method: "PUT"
});
}
When I request from my Angularjs service file I get: error 400 (bad request) if the service has a Content-Type = multipart / form-data
While I get a 415 (unsupported media type) error if the service has a Content-Type = "application / x-www-form-urlencoded; charset = utf-8" or "application / json; charset = utf-8" or "application / form-data ".
I am developing the front-end in javascript and html5, I did not find anything in the web that can help me as the FormDataMultiPart object does not exist in javascript.
I tried to format the data to send in many ways but it always returns 400 or 415.
How should I format the data to send to the rest call?
And how should the Content-Type be in the headers?

How to use AngularJS $http to send FormData
The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XHR Send method. It uses the same format a form would use if the encoding type were set to multipart/form-data.
var formData = new FormData();
formData.append('type', type);
formData.append('description', description);
formData.append('photo', photo);
return $http({
url: PATH_REST_SERVICES + '/nomeServizio',
headers: {"Content-Type": undefined },
data: formData,
method: "PUT"
});
It is important to set the content type header to undefined. Normally the $http service sets the content type to application/json. When the content type is undefined, the XHR API will automatically set the content type to multipart/form-data with the proper multi-part boundary.

in java code you need to write code like this:
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
for more you can refer bellow example and link :-
https://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/

Related

Spring boot unsupported media type with multipart request

I am trying to send a file and two json objects to my Spring Boot backend with a multipart POST request but I always get a 415 http response. Here is a list of things that I already tried to do:
Send each object as a Blob file with an application/json content type as suggested here
Send each object as a String as suggested here
Add contentType: false and processData: false in the ajax request as suggested here
Use #RequestParam instead of #RequestPart in Spring Boot controller
What am I missing?
Here is the request:
const data = new FormData();
data.append('file', new Blob([file], {type: 'multipart/form-data'}));
data.append('entity1-info', new Blob([JSON.stringify(entity1Object)], {type: 'application/json'}));
data.append('entity2-info', new Blob([JSON.stringify(entity2Object)], {type: 'application/json'}));
return axios({
method: 'post',
url: url,
headers: {'Authorization': `Bearer ${idToken}`},
data: data,
contentType: false,
processData: false
});
And here is my controller in Spring Boot:
#PostMapping("/upload")
public ResponseEntity<String> uploadFile(#NotEmpty #RequestPart("file") MultipartFile multipartFile, #NotNull #RequestPart("entity1-info") Entity1 entity1, #NotNull #RequestPart("entity2-info") Entity2 entity2, HttpServletRequest request) {
log.debug(request);
...
return ResponseEntity.ok("ok");
}
You have to set the "Content-Type" to the header
Content-Type:multipart/form-data
I'm using similar to the below curl command and it's working fine.
curl -v -H "Content-Type:multipart/form-data" -F "entiry1-info=#person1;type=application/json" -F "entiry2-info=#person2;type=application/json" -F "file=#logo.png;type=multipart/form-data" -X POST http://<IP_Address>:8080/api/upload
Note: above person1 and person2 are json files.
I eventually found the reason why I was always getting 415 http response from my Spring Boot backend.
The problem was that the url of the request was wrong. It was pointing to an endpoint that was expecting only json data and not multipart. And that's why Spring Boot was returning Unsupported media type.
Hope this could help someone else.

How to encode JSON data in application/x-www-form-urlencoded using Axios?

I have to make a post request to an API endpoint and it is required that the body of the request is encoded in application/x-www-form-urlencoded.
Here is what I am currently doing:
// Request data
const data = {
grant_type: "client_credentials",
};
// Request configuration
const config = {
method: "post",
url,
data,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization:
"Basic " +
Buffer.from(clientId + ":" + clientSecret).toString("base64"),
},
};
return axios(config).then(.....
As you can see, I have my data in JSON format, so how can I pass it encoded in application/x-www-form-urlencoded?
Any ideas? Thank you.
application/x-www-form-urlencoded means you can:
Send FormData body: axios post request to send form data
Or send data in the url query string: How to post query parameters with Axios?
You can also combine both.
This encoding is often used when JSON encoding doesn't meet the requirements e.g. sending files. You could send a file in a json string but that would be a base64 encoded file as string which increases the size.
This:
JSON.stringify(data);
will return
'data = {"grant_type": "client_credentials"}'

Make a correct POST request and get response data

I have an application hosted on pythonanywhere.com. It throws a 400 error if sended data does not contain data property, otherwise it returns a response data. This is Flask code of the server:
#app.route('/api', methods=['POST'])
def get_post():
if not request.json or not 'data' in request.json:
abort(400)
data = request.json['data']
# do something with the data...
return jsonify({'response': str(data)}), 200
And my front-end part of application should send a POST request with a data and get a response. I am trying to use fetch but it gets a 400 error though I send a JSON object with a data object:
function sendData(value) {
data = { 'data': value };
fetch('http://' + appUrl, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
mode: 'no-cors',
body: JSON.stringify(data),
})
.then(data => { return data.json() })
}
Also I tried to use XMLHttpRequest:
var xhr = new XMLHttpRequest();
xhr.open("POST", 'http://' + appUrl, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(data);
But I can't find out how to disable CORS and get a response data.
if you are having CORS issue, always check if the server accept your origin of request (other than pythonanywhere.com) if not, you should allow it from your server.
you mentioned that you are using Flask as your backend, you might want to check out this library:
https://flask-cors.readthedocs.io/en/latest/
if you follow the docs from the link, you can allow, accept http request depends on the parameter you provided.
Happy Coding

Angular + PHP: Simplest way to POST an object?

I'm studying php and angular. Currently exploring the possibilities to send data to server side using $http service. This is what I came up with and it seem to work, but it doesn't look elegant.
Angular code:
$http({
method: 'POST',
url: 'server.php',
data: "newUser=" + JSON.stringify(user),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
} // set the headers so angular passing info as form data (not request payload)
})
.success(function (respose) {
var x = JSON.parse(respose);
console.log(JSON.parse(x));
}).error(function (err) {
console.log(err);
console.log("some kind of error");
});
This is my php code to receive the data and return it:
if (isset($_POST["newUser"])) {
$newUser = $_POST["newUser"];
echo json_encode($newUser);
}
Why do I have to specify the name of the json I'm passing? I mean the newUser prefix under the data of the request.
Secondly, why do I have to json.parse twice the response in order to convert it back to a JS Object?
Why to I have to specify the headers in order to pass a simple JSON string?
Q1. Why do I have to specify the name of the json I'm passing? I mean the newUser prefix under the data of the request.
Q3. Why to I have to specify the headers in order to pass a simple JSON string?
In PHP, you have global arrays like $_POST & $_GET to receive the data extracted from the request that are on the form of key=value.
And $_POST is filled when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type.
So in order to use these global arrays, you have to full-fill these two conditions
Okay the alternative way is to use php://input stream to directly read the raw input, so you can send the json string directly.
file_get_contents(“php://input”);

415 (Unsupported Media type) when trying to post formData to Spring

I want to post pdf files to spring, using formData.
Javascript Code:
var formData=new FormData();
formData.append("file",file);
$http({
method: 'POST',
accept: 'multipart/form-data',
url: '/upload',
contentType: 'multipart/form-data',
data: formData
}).then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
console.log(response);
});
Spring Code:
#Controller
public class upload {
#RequestMapping(value = "/upload", method = RequestMethod.POST,consumes="multipart/form-data", headers = "content-type=multipart/form-data")
private void upload(MultipartHttpServletRequest request, HttpServletResponse response){
}
}
I get the Error "415 (Unsupported Media Type)" when using this code. I tried to post json objects (application/json instead of multipart/form-data) and it worked perfectly.
Is multipart/form-data the wrong type to use in my case? Or is there just an error in the code?
I would be very thankful for potential help.
The Accept part is wrong, you don't need that.
$http don't handle that much files natively, use https://github.com/danialfarid/ng-file-upload in order to be able to handle files, add validation on your form about the files (size, type, ...).
For a raw $http solution check the 2nd most upvated answer here : Angularjs $http post file and form data

Categories

Resources