$http post multipart/form-data boundary not set - angularjs

I am setting the boundary for the below post call but on chrome the boundary looks different from the one I set. how do I get my custom boundary "--test" to show up on the request payload?
var url = '/site/apkUpload';
var deferred = $q.defer();
console.log(formdata);
$http.post(url, formdata, {
processData: false,
headers: {'Content-Type': "multipart/form-data; charset=utf-8; boundary='--test'",
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
'x-access-token': token,
'cache-control': 'max-age=0'}
})
.success(function (response) {
deferred.resolve(response);
})
.error(function (reject) {
deferred.reject(reject);
});
return deferred.promise;
Request payload on chrome:
------WebKitFormBoundaryB5LjM2a6Qly3Xruj
Content-Disposition: form-data; name="packageName"
helo1
------WebKitFormBoundaryB5LjM2a6Qly3Xruj
Content-Disposition: form-data; name="name"
......
Thanks a lot!

I can interpret your question in 2 ways:
You are talking about why you are not getting ------WebKitFormBoundaryB5LjM2a6Qly3Xruj in the POST request header, which you are getting in the request payload. I had the same issue while sending a multi-part formdata using $http.post (also I was using FormData).The solution to this is using $http(config).To my understanding $http.post underlying uses $http() itself to generate XMLHttpRequest object, which should run the multipart/form-data encoding algorithm to set the multipart boundary in payload and the header as well. In $http.post, it seems whenever you give a custom config object it overwrites the header generated by the algorithm. This answer is also helpful.
If you just want to add a custom multipart boundary in the content-header, then you can achieve that by add a tranformRequest function in the config object:
var url = '/site/apkUpload';
var deferred = $q.defer();
console.log(formdata);
$http.post(url, formdata, {
processData: false,
transformRequest: function (data, headers) {
var boundary = yourCustomLogic();
headers()['Content-Type'] = 'multipart/form-data;charset=utf-
8;boundary=' + boundary;
},
'Accept': ...,
'x-access-token': token,
'cache-control': 'max-age=0'
})
.success( function () {...});

Related

Multiple response types in a single $http call [duplicate]

I have an Angular 1.x application that is expecting to receive a binary file download (pdf) using a $http.post() call. The problem is, I'd like to alternatively get a processing error message that's sent as json. I can do this with the config
headers: {
'Accept': 'application/pdf, application/json'
}
The problem is I have have to set responseType: 'arraybuffer', otherwise the pdf binary is escaped (or altered such that it doesn't load). However, that prevents the json from being read or interpreted correctly.
How can I have both?
Edit: I'm going to try to clarify; perhaps my understanding is incorrect.
$http({
method: 'POST',
url: "/myresource",
headers: {
'Accept': 'application/pdf, application/json'
},
responseType: 'arraybuffer'
})
.then(
function(response) {
// handle pdf download via `new Blob([data])`
}, function(response) {
// pop up a message based on response.data
}
)
In a scenario where I return a pdf data block and a http status of 200, the first function handles the response and prompts the user to save the file. However if the status is an error (422), the response.data is undefined. I assume this is because the responseType is preventing the json from being handled correctly.
If I remove the responseType line, the error data is correctly read, but when the pdf is saved, some of the file bytes aren't correct and it's effectively corrupted. I assume this is because the file is being encoded because javascript was expecting a string.
An XHR responseType property can not be changed after a response has been loaded. But an arraybuffer can be decoded and parsed depending on Content-Type:
var config = {
responseType: "arraybuffer",
transformResponse: jsonBufferToObject,
};
function jsonBufferToObject (data, headersGetter, status) {
var type = headersGetter("Content-Type");
if (!type.startsWith("application/json")) {
return data;
};
var decoder = new TextDecoder("utf-8");
var domString = decoder.decode(data);
var json = JSON.parse(domString);
return json;
};
$http.get(url, config);
The above example sets the XHR to return an arraybuffer and uses a transformResponse function to detect Content-Type: application/json and convert it if necessary.
The DEMO on PLNKR

CORS post call not working in Angularjs

I am trying to implement cross-origin post call from angularjs application, then I get the following error.
Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.
But, when I make a Ajax call it works properly.
How HTTP post call work in angularjs?
Ajax call
$.ajax({
type: 'POST',
url: getAccessTokenUrl,
data: JSON.stringify(clintdata),
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function(resultData) {
console.log(resultData);
},
error: function (request, status, error) {
console.log(status);
}
});
Angularjs HTTP call
$http({
method: 'POST',
url: getAccessTokenUrl,
data: clientdata,
headers: {
'Authorization': undefined,
'Auth-Token': undefined
}
}).then(function(res){
console.log(res);
}, function(err){
console.log(err);
});
I have some default setting. Authorization is for others REST
$http.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8;' ;
$http.defaults.headers.common['Auth-Token'] = 'X-Requested-With';
$http.defaults.headers.common['Authorization'] = $('#Authorization').val();
Access-Control-* headers are response headers. They come from the server in response to a request. You do not apply them to your request headers.
If your jQuery request works correctly without adding any additional headers, then your AngularJS request should work the same.
The equivalent jQuery request in AngularJS (including removing the Authorization and Auth-Token headers you've set via defaults) is
$http.post(getAccessTokenUrl, clientdata, {
headers: {
Authorization: undefined,
'Auth-Token': undefined
}
}).then(response => {
console.log(response.data)
})
or the long version
$http({
method: 'POST',
url: getAccessTokenUrl,
data: clientdata,
headers: {
Authorization: undefined,
'Auth-Token': undefined
}
}).then(...)
AngularJS by default...
POSTS requests as application/json content-type
Serializes the data property to JSON
Expects a JSON response
Resolves the $http promise with a response object with the response body parsed as JSON into the data property
Remove the following setting
$http.defaults.headers.common['Auth-Token'] = 'X-Requested-With';
$http.defaults.headers.common['Authorization'] = $('#Authorization').val();
Add Authorization header dynamically from Interceptor
request: function(config) {
if (angular.isUndefined(config.skipInterceptor) || !config.skipInterceptor) {
// add Authorization token
}
return config;
}
Http call like this
$http.post('your url', {
skipInterceptor: true
})

I am trying to upload a file to Django server using angularjs 1.6.5. I am not able to upload file using $http.patch method

Using Angularjs 1.6.5 I am trying to upload a file to the Django server. When I try to upload the file I am not sure what type of 'Content-Type' header should be passed with the $http.patch method. Here is the following my Angular apps config:-
var app = angular.module("edit_modules", []);
app.config(function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.common['Accept'] = 'application/json, text/javascript';
});
And this is my patch method:-
$http.patch(url, data, {
headers: {'Content-Type': 'application/json; charset=utf-8' }
}).then(successCallback, errorCallback);
function successCallback(response){
console.log("Success");
console.log(response);
};
function errorCallback(error){
alert("Error Uploading!");
console.log(error);
};
When I pass {'Content-Type': 'application/json; charset=utf-8' } through the Header I get the following error:-
"The submitted data was not a file. Check the encoding type on the form."
Status :- 400
Since its content-type is file I used the following header {'Content-Type': 'multipart/form-data; charset=utf-8'} . But then I got this error:-
Multipart form parse error - Invalid boundary in multipart: None
Status :- 400
As suggested in the link here I tried the following header as well {'Content-Type': undefined} But this as well did not resolve my problem and I got the following error:-
Unsupported media type "text/plain;charset=UTF-8" in request.
Status :- 415
However when I tried with simple text fields the PATCH method worked with the header supplied being {'Content-Type': 'application/json; charset=utf-8' }. I am not sure where the problem is. I even tried to see the console for what data was being set to be patched
data = {
"video": element.files[0]
};
console.log(data);
THIS is what i got on console:-
{video: File(99861)}video: File(99861) {name: "Capture2.PNG", lastModified: 1517491665223, lastModifiedDate: Thu Feb 01 2018 18:57:45 GMT+0530 (India Standard Time), webkitRelativePath: "", size: 99861, …}
any help is much appreciated.
Referring to the answer here I found that you need to attach the File Object to be sent using FormData. Also you need an additional header in config transformRequest: angular.identity,. Here is the successful PATCH method that worked for me.
var fd = new FormData();
fd.append('video', element.files[0]);
$http.patch(url, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(successCallback, errorCallback);
function successCallback(response){
console.log("Success");
console.log(response);
};
function errorCallback(error){
alert("Error Uploading!");
console.log(error);
};
In the second line 'video' is the REST API Endpoint's variable where my file will be stored. In order to avoid the error
Multipart form parse error - Invalid boundary in multipart: None
I have left the headers: {'Content-Type': undefined}.

Can AngularJS set the responseType after a response has been received?

I have an Angular 1.x application that is expecting to receive a binary file download (pdf) using a $http.post() call. The problem is, I'd like to alternatively get a processing error message that's sent as json. I can do this with the config
headers: {
'Accept': 'application/pdf, application/json'
}
The problem is I have have to set responseType: 'arraybuffer', otherwise the pdf binary is escaped (or altered such that it doesn't load). However, that prevents the json from being read or interpreted correctly.
How can I have both?
Edit: I'm going to try to clarify; perhaps my understanding is incorrect.
$http({
method: 'POST',
url: "/myresource",
headers: {
'Accept': 'application/pdf, application/json'
},
responseType: 'arraybuffer'
})
.then(
function(response) {
// handle pdf download via `new Blob([data])`
}, function(response) {
// pop up a message based on response.data
}
)
In a scenario where I return a pdf data block and a http status of 200, the first function handles the response and prompts the user to save the file. However if the status is an error (422), the response.data is undefined. I assume this is because the responseType is preventing the json from being handled correctly.
If I remove the responseType line, the error data is correctly read, but when the pdf is saved, some of the file bytes aren't correct and it's effectively corrupted. I assume this is because the file is being encoded because javascript was expecting a string.
An XHR responseType property can not be changed after a response has been loaded. But an arraybuffer can be decoded and parsed depending on Content-Type:
var config = {
responseType: "arraybuffer",
transformResponse: jsonBufferToObject,
};
function jsonBufferToObject (data, headersGetter, status) {
var type = headersGetter("Content-Type");
if (!type.startsWith("application/json")) {
return data;
};
var decoder = new TextDecoder("utf-8");
var domString = decoder.decode(data);
var json = JSON.parse(domString);
return json;
};
$http.get(url, config);
The above example sets the XHR to return an arraybuffer and uses a transformResponse function to detect Content-Type: application/json and convert it if necessary.
The DEMO on PLNKR

AngularJS HTTP GET request returning cached data

In my AngularJS app I am sending HTTP GET request as below.
MyService.HttpReq("testUrl", "GET", null);
HttpReq Method is defined in a service and implemented as below:
this.HttpReq = function(URL, method, payload)
{
$http({
url: URL,
method: method,
cache: false,
data: postData,
headers: {
'Content-Type': 'application/json',
}
}).success(function(response)
{
console.log("Success: "+JSON.stringify(response));
}).error(function(data, status)
{
console.error("Error");
});
}
First of all is this the right way of sending HTTP request in AngularJS?
The problem that I am facing is, some times I get cached data as response and HTTP request is not hitting the server. what can be the issue?
UPDATE
As per the comment and answer I have updated my HTTP request code as below, but still getting same issue.
this.HttpReq = function(URL, method, payload)
{
$http({
url: URL,
method: method,
cache: false,
data: payload,
headers: {
'Content-Type': 'application/json',
'Cache-Control' : 'no-cache'
}
}).
then(
function(response)
{
var data = response.data;
console.log("Success: "+JSON.stringify(data));
},
function(response)
{
var data = response.data || "Request failed";
var status = response.status;
console.error("Error: "+JSON.stringify(data));
}
);
}
IE Browsers will catch ajax get requests even if we add cache control headers to the response. Only way i found to solve the issue is to add some random parameter to the request. Please make sure the api have no problem even if you send extra parameters
MyService.HttpReq("testUrl?ts=" + Date.now(), "GET", null);
Just add cache: false attribute to config object.
https://docs.angularjs.org/api/ng/service/$http#caching
Also you can add header: 'Cache-Control' : 'no-cache'

Resources