Cloudinary Base64 Image uploading in angularjs - javascript

$http({method: 'POST',
url: $rootScope.CLOUDINARY_CONFIG.upload_url,
data : {
file : canvasImage,
resource_type : 'image',
format: "jpg",
timestamp : 1375363550,
api_key : $rootScope.CLOUDINARY_CONFIG.api_key,
signature : signature,
public_id : scope.model.public_id
},
headers : {"X-Requested-With": "XMLHttpRequest", "Content-Type" : "multipart/formData"}
}).success(function(data, status, headers, config) {
console.log("success");
}).error(function(data, status, headers, config) {
console.log("fail");
});
I am trying to upload a base64 image to cloudinary account. I have already checked whether the signature, api key, upload url and canvasImage are correct.
Yet whenever the request is sent,
I get an error in response :
{"error":{"message":"Missing required parameter - file"}}
On checking the request payload i can see the file parameter being passed.
The canvasImage is the base64 jpg. of the sort - data:image/jpeg;base64,/9j/4AAQSkZJRgABA.
Can't find anything of this sort in the cloudinary documentation.

Firstly, look into the FormData object. You'll want to use that if you're uploading multi-part form data.
Basically, the FormData object allows you to append files, blobs, and strings (if you attach something that isn't of those three, it will stringify it) using the only function that it has, append i.e:
var newForm = new FormData();
newForm.append('fileName', file);
newForm.append('api_key', $rootScope.CLOUDINARY_CONFIG.api_key);
newForm.append('signature', signature);
newForm.append(public_id, scope.model.public_id);
and so on..
Next.
Set your content-type to undefined instead of multi-part form data. This seems unintuitive, however, what happens is that the browser will automatically set the proper boundary for you and will automatically set the content-type back to multipart/formdata.
Additionally, add a transformRequest to the config set to angular.identity. The browser will try to serialize your form data, therefore you need to stop it from doing so by setting transformRequest to angular.identity.
The overall $http request should look something like this:
$http.post(url, newForm, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(data){
// success
})
.error(function(err){
// log error
})
Also note that FormData is tricky to deal with you because if you console your FormData object, i.e.(console.log(newForm)) all it will show is: FormData {append: function}

Related

Using FormData() inside fetch api is not working

I read all over but couldn't find the answer.
When I use FormData(), it returns status 404 bad request.
However, if I pass the data (hardcoded) as in const requestBody (example below), it works perfectly.
This is my code:
var formData = new FormData();
formData.append("nickname", "johxns");
formData.append("password", "john_password");
formData.append("email", "john#server.com");
// If I do it this way, and assign this to body inside fetch, it works perfectly
// const requestBody = '{"nickname": "johxns","password":"john_password","email":"john#server.com"}';
fetch("http://localhost:5000/create_user", {
// if instead of formData, I assign requestBody to body, it works!
body: formData,
headers: {
"Content-Type": "application/json"
},
method: "POST"
}).then(function(response) {
return response.text();
}).then(function(data){
console.log('data', data);
}).catch(function(err){
console.err(err);
});
I already tried with URLSearchParams, but still couldn't make it work.
Thanks.
You shouldn't set the Content-Type header to application/json if you're not sending json. According to this answer, you don't need to set the Content-Type header.
body data type must match "Content-Type" header
Using Fetch
You should either send json data if you set Content-Type to application/json or not set any Content-Type if using FormData API since the fetch function is able to determine the correct Content-Type.
See here for more informations.

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

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/

responseType property of the XMLHttpRequest to accept multiple values

I have a situation where the $http reponseType is dependent on url query parameter. When output-target=html and if I don't mention responseType at all, I am able to get the response in html properly.
However when output-target=xls, I need to do this, to make it work
and have responseType set to arraybuffer (to get response in excel)
var blob = new Blob([data], {type: "application/vnd.ms-excel"});
$http({
method: 'GET',
url: "https://xyz/abc?output-target=" + $scope.outputTarget,
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'},
responseType: arraybuffer //for $scope.outputTarget=xls
})
I need something which will accept all kind of response types. If that option is not available, what is the way around?
I also tried passing function to responseType but that didn't work either.
responseType: (function () {
if($scope.outputTarget === "table/excel;page-mode=flow") {
var arraybuffer
return arraybuffer;
} else {return;}
})()
responseType documentation
What we've done in the project is to have a wrapper over $http called "ajax" and in this service we provide extra parameters to get/post/call/put type of calls and enhance the headers with Content-Type (in your case) just for that particular request. The service provides a default of course (the most common ajax calls headers).
I have kept the responseType to be arraybuffer and converted the buffer to string when the output target = html.
var decodedString = String.fromCharCode.apply(null, new Uint8Array(buf));

How to access file uploaded by $http and HTML5 FileReader

I am trying to upload an image inside an Angular app, the code looks like this:
var f = document.getElementById('product-image').files[0],
r = new FileReader();
r.onloadend = function (e) {
var data = e.target.result;
$http({
method: 'POST',
data: data,
url: host + '/uploadFile?' + $rootScope.user._id,
headers: {
'Content-Type': 'multipart/form-data',
'X-File-Name': f.name,
'X-File-Size': f.size,
'X-File-Type': f.type
}
})
.success(function (data, status, headers, config) {
console.log(data)
});
}
r.readAsArrayBuffer(f);
When I have a look at Chrome Header fields of the request, they all look good with values.
Now, how do I access and save that file from the backend endpoint in NodeJS and Express? Do I look inside req variable as usual? Where do I look for the file and its content and meta?
basically, your post request is not 'multipart/form-data', and the data you sent to server is just binary array.
So you could just using NodeJS to save the trunk of binary data to some place.
You need to handle the data different way from normal form upload with files.
If you really want the server to handle the file upload as normal way, you could check the https://github.com/danialfarid/angular-file-upload

AngularJS: PUT binary data from ArrayBuffer to the server

Ok, so I try to read a PDF file like this:
reader.readAsArrayBuffer(file);
and then try to send it to the server using $http like this:
$http.put(url, data, {headers: {'Content-Type': 'application/pdf'}});
So, just read & send the binary to the server in raw form. According to some resources I found, passing an ArrayBuffer to XHR should work, but passing it as data to $http just results in a request body like this: {} and Content-Length=2
Reading the file readAsBinaryString() results in a corrupted file (and is apparently deprecated for that very reason)
The use case seems so trivial to me, am I missing something?
Chrome 36, Angular 1.2.20
You have to use reader.readAsArrayBuffer(file); then in the onload callback create an ArrayBufferView from the result:
new Uint8Array(reader.result)
pass that data to $http and overwrite the transformRequest property so angularjs doesn't encode your array into json:
reader.onload = function() {
$http({
method: 'PUT',
headers: {'Content-Type': 'application/pdf'},
data: new Uint8Array(reader.result),
transformRequest: []
})
};
reader.readAsArrayBuffer(file);
Is it because you are just handing the $http method the array buffer instead of writing that buffer into a byte array? If so what you are posting to the server is probably just the arraybuffer object.
Check this post on how to write ArrayBuffer to byte array:
How do I read binary data to a byte array in Javascript?
There are two problems in your request.
You need to supply a data view to $http function.
So, data should be new DataView(data) or new Uint8Array(data) etc
$http always attempt to send the data as json. You can prevent this if you override the transform function. The transform function is the agent that is responsible for transforming your binary into json.
So, you should add transformRequest: [] property to your request.
Example:
var request = $http({
method: 'PUT',
url: 'example.com',
data: new Uint8Array(data),
headers: {'Content-Type': 'application/octet-stream'},
transformRequest: [],
responseType: 'arraybuffer'
});

Categories

Resources