Pass array of data in angularjs multipart - arrays

I have an array of colors and sizes, and some other data like product_name and images, I am able to send image files and product_name but when I attach color_and_sizes array then it says 500 error
Here is my Code :(Angularjs and Laravel Controller )
Basically I want to save all the details in the database but I am unable to save the color and sizez details.
$scope.admin_add_product=function(){
var product_name=$scope.txtProductname;
var product_description=$scope.tarDescription;
var price=$scope.txtprice;
var unit_in_stock=$scope.txtunitinstock;
var unit_weight=$scope.txtweight;
var file = $scope.front_image;
var file2=$scope.back_image;
var file3=$scope.left_side_image;
var file4=$scope.right_side_image;
var main_image=$scope.main_image;
var large_image=$scope.large_image;
var category_id=$scope.selectedCategory.category_id;
var sub_category_id=$scope.selectedSubCategory.sub_category_id;
var sub_sub_category_id=$scope.selectedSubSubCategory.sub_sub_category_id;
var product_key=$scope.addProductOption;
var tags=$scope.txt_tags;
var aditional_information=$scope.txt_aditional_information;
var temp_color_and_size=[];
temp_color_and_size=$scope.color_and_size;
console.log(temp_color_and_size);
var uploadUrl = 'http://web.com/app/add_product';
fileUpload.uploadFileToUrl(file,file2,file3,file4,main_image,large_image, product_name,product_description,price,category_id,sub_category_id,sub_sub_category_id,unit_in_stock,unit_weight,product_key,tags,aditional_information ,temp_color_and_size, uploadUrl);
}
/* ---------------------------------------------------- Color and Sizes -------------------------------------------------- */
$scope.color_and_size=[];
$scope.Add=function(){
var c_and_s=[];
c_and_s.color_name = document.getElementById('cl1').value;
var s;
if($scope.sizes!=null)
{
for(var i=0;i<$scope.sizes.length-1;i++)
{
if($scope.sizes[i+1]>=0 && $scope.sizes[i+1]<=9)
{
}
else
{
if($scope.sizes[i+2]>=0 && $scope.sizes[i+2]<=9)
{
}
else
{
$scope.sizes = $scope.sizes.substring(0, i+1);
}
}
}
console.log($scope.sizes);
$scope.size=$scope.sizes.split(',');
c_and_s.sizes=$scope.size;
}
$scope.color_and_size.splice(0,0,c_and_s);
console.log($scope.color_and_size);
document.getElementById('cl1').value="#000000";
$scope.sizes="";
}
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file,file2,file3,file4,main_image,large_image,product_name,product_description,price,category_id,sub_category_id,sub_sub_category_id,unit_in_stock,unit_weight,product_key,tags,aditional_information,temp_color_and_size, uploadUrl){
console.log(product_name);
console.log(product_description);
console.log(price);
console.log(unit_in_stock);
console.log(unit_weight);
console.log(file);
console.log(temp_color_and_size);
console.log(product_key);
console.log(tags);
console.log(aditional_information);
var payload = new FormData();
payload.append("product_name", product_name);
payload.append('product_description', product_description);
payload.append('price', price);
payload.append('unit_in_stock', unit_in_stock);
payload.append('unit_weight', unit_weight);
payload.append('file', file);
payload.append('file2', file2);
payload.append('file3', file3);
payload.append('file4', file4);
payload.append('main_image', main_image);
payload.append('large_image', large_image);
payload.append('product_key', product_key);
payload.append('tags', tags);
payload.append('aditional_information', aditional_information);
payload.append('temp_color_and_size', temp_color_and_size);
return $http({
url: uploadUrl,
method: 'POST',
data: payload,
//assign content-type as undefined, the browser
//will assign the correct boundary for us
headers: { 'Content-Type': undefined},
//prevents serializing payload. don't do it.
transformRequest: angular.identity
})
.then(function (response){
alert('Product Added Successfully');
window.location = "http://web.com/add_product"
},function (error){
});
}
}]);
Please help me to resolve this problem.

Your question is not clear to me but I think the problem is that all properties of the formData object apart from temp_color_and_size are string type and temp_color_and_size is a javascript object. This might solve your problem.
payload.append('temp_color_and_size', JSON.stringify(temp_color_and_size);
You have to deserialize JSON string on the server side.

Related

blob file edit and upload in angularjs

I am fetching a list of files (which may be of any type) from mysql database and converting them to byte[] and returning all the files of a particular user as an array of files in spring boot.
Now I need to display all the files in the front end and provide an option to edit the file so that the user can remove the already existing file with the new file.
So Whenever a particular file is edited I have to upload the file from front end using angular js.
The Problem is I am getting the files as an array in response.data. I am facing a problem here like, How to edit the a particular file in that array and send the list of files to the backend to store them.I tried to traverse through array of files and store each file as a blob object, but I am not sure of what is the content type of each file as it can be any type of file(.bmp,.pdf,.docx,.tif etc).
Also I am not sure if it is the rightway to do for editing the files, because it may alter the content of the existing file or may change the type of the exixsting file.
So Please suggest me a way to get the file from the database and edit the file if necessary and then push it back to the database.
My controller and services below:-
angular.module("app").service("serviceCalls", function($q, $rootScope, $http) {
this.landOwnerEditProfile = function(email){
var differed = $q.defer();
$rootScope.config.headers.Authorization = sessionStorage.Authorization;
$http
.get($rootScope.URL + "/landownerDetails/"+email+"/", $rootScope.config,{
responseType: 'blob'
})
.then(function(response) {
console.log("coupon service success");
differed.resolve(response);
})
.catch(function(response) {
differed.reject(response);
});
return differed.promise;
};
this.updateLandOwnerProfile = function(details, email) {
var differed = $q.defer();
$rootScope.config.headers.Authorization = sessionStorage.Authorization;
var formdata = new FormData();
// console.log($("#file"));
formdata.append("email", email);
formdata.append("fname", details.user.fname);
formdata.append("lname", details.user.lname);
formdata.append("city", details.user.city);
formdata.append("phone1", details.user.phone1);
formdata.append("phone2", details.user.phone2);
formdata.append("phone3", details.user.phone3);
formdata.append("streetAddressLine1", details.user.streetAddressLine1);
formdata.append("streetAddressLine2", details.user.streetAddressLine2);
formdata.append("stripeApiKey", details.user.stripeApiKey);
formdata.append("zipcode", details.user.zipcode);
formdata.append("businessName", details.user.businessName);
formdata.append("landOwnerEditProfile", true);
// var input_files = document.getElementsByClassName("files");
// for (var i = 0; i < input_files.length; i++) {
// console.log(input_files[i].files);
// for (var file of input_files[i].files) formdata.append("file", file.name);
// }
// formdata.append("file", input_files);
// for (var key of formdata.entries()) {
// console.log(key[0] + ", " + key[1]);
// }
for (var i = 0; i < details.files.length; i++) {
formdata.append("file", details.files[i].file);
}
$http
// .post("http://localhost:8090/", formdata, {
.post($rootScope.URL + "/user/landownerDetails/editProfile/"+email+"/", formdata, $rootScope.config,{
transformRequest: angular.identity,
headers: {
"Content-Type": undefined,
// "Authorization":$rootScope.config.headers.Authorization
}
})
.then(function(response) {
// console.log(response);
if(response.data.status!=true){
throw new Error(" Details Not Updated ");
}
console.log("Details updated success");
differed.resolve(response);
})
.catch(function(response) {
console.log("rejected", response);
differed.reject(response);
});
return differed.promise;
}})
angular
.module("app")
.controller("landOwnerEditProfile", function($state, $scope, $location, serviceCalls, $filter, $stateParams,$timeout) {
$scope.files = [];
serviceCalls.landOwnerEditProfile(sessionStorage.emailId)
.then((response)=>{
console.log(response.data);
let status = response.status;
if(status===200){
let landownerDetails = response.data;
let landowner = landownerDetails.dayleasingusers;
let userdocuments = landownerDetails.userdocuments;// userdocument is an array containing the files
$scope.user = {};
$scope.property={};
$scope.user.fname = landowner.fname;
$scope.user.lname = landowner.lname;
$scope.user.streetAddressLine1 = landowner.address1;
// $scope.user.streetAddressLine2 = landowner.address2 ||'sdasd';
$scope.property.propertyType = landowner.state || 'Alabama';
$scope.user.city = landowner.city;
$scope.user.zipcode = parseInt(landowner.zipCode);
$scope.user.phone1 = !!landowner.phone?parseInt(landowner.phone.substring(0,3)):null;
$scope.user.phone2 = !!landowner.phone?parseInt(landowner.phone.substring(3,6)):null;
$scope.user.phone3 = !!landowner.phone?parseInt(landowner.phone.substring(6)):null;
$scope.user.stripeApiKey = landowner.stripeApiKey;
$scope.user.businessName = landowner.businessName;
$scope.files = [];
for(let doc of userdocuments){
let blob = new Uint8Array(doc.filedata);
$scope.files.push({file:new Blob([blob],{ type:'contentType'})}); //I am not sure of the contentType here.
// $scope.files.push({file:new Blob([doc.filedata],{ type:'multipart/form-data'},doc.filename)});
// $scope.files.push({file:new File([doc.filedata],doc.filename)});
}
}
else{
throw new Error(response.statusText);
}
})
.catch((error)=>{
console.log(error);
})
serviceCalls.updateLandOwnerProfile($scope, sessionStorage.emailId)
.then(function(response) {
console.log(response);
})
.catch(function(error) {
})

FormData append not working with $http post

I want to submit info to an online server and it requires that I send that using FormData.
So I am using the following function for that
var my_app = angular.module("my-app",[])
my_app.controller("MainController", function($scope, $http){
$scope.master = {title: "Title",desc: "Desctibe", tags: ["One","Two"], category: ["1","2"] };
var url = "http://freedoctor.southeastasia.cloudapp.azure.com/api/forum/create";
var config = {"headers":{"Authorization":"JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU5MzEwNDUxZjk3MjJmZTQyODE1NTIxYSIsInJvbGUiOiJwYXRpZW50IiwiaWF0IjoxNDk3NDE4ODA3fQ.ODrSlYwxvrPb93IzHW3s-7NIVFsOL4pKzqZx8yMqWWE"}};
$scope.booking = function(){
$scope.title=$scope.user.title;
$scope.desc=$scope.user.desc;
$scope.tags=$scope.user.tags;
$scope.category=$scope.user.category;
$scope.askedTo=$scope.user.askedTo;
var info = new FormData();
info.append("title", $scope.title);
info.append("desc", $scope.desc);
info.append("tags", $scope.tags);
info.append("category", $scope.category);
$http.post("http://localhost:8080/"+url, info, config).then(
function(response){
console.log(response);
$scope.reply = response.data;
},
function(response){
console.log(response);
$scope.reply = response.data;
});
}
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
});
So whenever I call booking function I get an internal server error
SyntaxError: Unexpected token -
at parse (/home/freedoctor/fdhbackend/node_modules/body-parser/lib/types/json.js:83:15)
at /home/freedoctor/fdhbackend/node_modules/body-parser/lib/read.js:116:18
at invokeCallback (/home/freedoctor/fdhbackend/node_modules/raw-body/index.js:262:16)
at done (/home/freedoctor/fdhbackend/node_modules/raw-body/index.js:251:7)
at IncomingMessage.onEnd (/home/freedoctor/fdhbackend/node_modules/raw-body/index.js:307:7)
at emitNone (events.js:86:13)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickDomainCallback (internal/process/next_tick.js:122:9)
I know the FormData is working as i checked it out with this
for (var pair of info.entries()) {
console.log(pair[0]+ ', ' + pair[1]);
}
The additional data that you are trying to pass along the formData object should be appended to the data property of the FormData Object. I once wrote the following function. Should work for you too:
this.uploadFile = function (url, dataToUpload) {
var data = new FormData();
data.append("file", dataToUpload.file); //if you want to upload files along, else ignore this line
data.append("data", angular.toJson(dataToUpload.data)); //you can pass an object containing additional data and then append it here to the data property
return $http.post(url, data, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
});
}
You can chain your .then callbacks to the returned object from this function.
Try this and update if you face any issue.

how to convert image file in byte array angular?

I am struggling converting image to byte array using client side script. I have to convert image to byte array, and pass this array to web service , so that the web services can save the image in server. Any one please help me.
$scope.file=function(user){
//console.log("hhhhh",angular.toJson($scope.user));
console.log(ContextService.object);
$scope.users=ContextService.object;
console.log($scope.user);
//$scope.file=$scope.file;
console.log($scope.user.file);
var file=$scope.user.file;
var bytes = [];
var fileReader = new FileReader();
fileReader.onload = function (e) {
var naveen=fileReader.result;
for (var i = 0; i < naveen.length; ++i)
{
bytes.push(naveen.charCodeAt(i));
bytes.push(0);
}
console.log("bytes",bytes);
$scope.call(bytes);
};
fileReader.onerror = function(err) {
console.log(err);
};
fileReader.readAsBinaryString(file);
$scope.call=function(bytes)
{
$scope.image=bytes;
}
$timeout(function() {
console.log("vvvvv",$scope.image);
$scope.users.file=$scope.image;
console.log("dsfdsfds",$scope.users);
var url = "http://127.0.0.1:8080/api/signup";
$http({
method : "POST",
url : url,
data :angular.toJson($scope.users),
headers : {
"content-type" : "application/json",
"Accept" : "application/json"
}
})
.success(function(data) {
console.log("Detail", angular.toJson(data));
$state.go("login");
});
}, 3000);

How to do unit testing using jasmine on that factory?

I try to make a unit test on that code that consists of factory that take behavior Name and contracts an http request in a closure ?
var app = angular.module("behaviour",[]);
var behaviour = app.factory('Behaviours',['http',function(http){
var BehavioursJson = $http.get('data.json');
return {
getBehaviour : function(behaviourName) {
if (BehavioursJson[behaviourName]) {
var behaviour = BehavioursJson[behaviourName];
return function (behaviourData, callback) {
var keys = Object.allKeys(behaviourData);
var headers = {};
var data = {};
var url = behaviour.path;
// some process to fill headers and data objects
$http({
method: behaviour.method,
url: url,
data: data,
headers: headers
}).then(function successCallback(response) {
callback(response,null);
},function errorCallback(error) {
callback(null,error);
});
}
};
return null;
}
}
}]);
Note: using jasmine

How to Display blob (.pdf) in an AngularJS app

I have been trying to display pdf file which I am getting as a blob from a $http.post response. The pdf must be displayed within the app using <embed src> for example.
I came across a couple of stack posts but somehow my example doesn't seem to work.
JS:
According to this doc, I went on and tried...
$http.post('/postUrlHere',{myParams}).success(function (response) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
$scope.content = fileURL;
});
Now from what I understand, fileURL creates a temporary URL that the blog can use as a reference.
HTML:
<embed src="{{content}}" width="200" height="200"></embed>
I am not sure how to handle this in Angular, the ideal situation would be to (1) assign it to a scope, (2) 'prepare/rebuild' the blob to a pdf (3) pass it to the HTML using <embed> because I want to display it within the app.
I have been researching for more than a day now but somehow I can't seem to understand how this works in Angular... And let's just assume the pdf viewer libraries out there weren't an option.
First of all you need to set the responseType to arraybuffer. This is required if you want to create a blob of your data. See Sending_and_Receiving_Binary_Data. So your code will look like this:
$http.post('/postUrlHere',{myParams}, {responseType:'arraybuffer'})
.success(function (response) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
});
The next part is, you need to use the $sce service to make angular trust your url. This can be done in this way:
$scope.content = $sce.trustAsResourceUrl(fileURL);
Do not forget to inject the $sce service.
If this is all done you can now embed your pdf:
<embed ng-src="{{content}}" style="width:200px;height:200px;"></embed>
I use AngularJS v1.3.4
HTML:
<button ng-click="downloadPdf()" class="btn btn-primary">download PDF</button>
JS controller:
'use strict';
angular.module('xxxxxxxxApp')
.controller('xxxxController', function ($scope, xxxxServicePDF) {
$scope.downloadPdf = function () {
var fileName = "test.pdf";
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
xxxxServicePDF.downloadPdf().then(function (result) {
var file = new Blob([result.data], {type: 'application/pdf'});
var fileURL = window.URL.createObjectURL(file);
a.href = fileURL;
a.download = fileName;
a.click();
});
};
});
JS services:
angular.module('xxxxxxxxApp')
.factory('xxxxServicePDF', function ($http) {
return {
downloadPdf: function () {
return $http.get('api/downloadPDF', { responseType: 'arraybuffer' }).then(function (response) {
return response;
});
}
};
});
Java REST Web Services - Spring MVC:
#RequestMapping(value = "/downloadPDF", method = RequestMethod.GET, produces = "application/pdf")
public ResponseEntity<byte[]> getPDF() {
FileInputStream fileStream;
try {
fileStream = new FileInputStream(new File("C:\\xxxxx\\xxxxxx\\test.pdf"));
byte[] contents = IOUtils.toByteArray(fileStream);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
String filename = "test.pdf";
headers.setContentDispositionFormData(filename, filename);
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
return response;
} catch (FileNotFoundException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
return null;
}
michael's suggestions works like a charm for me :)
If you replace $http.post with $http.get, remember that the .get method accepts 2 parameters instead of 3... this is where is wasted my time... ;)
controller:
$http.get('/getdoc/' + $stateParams.id,
{responseType:'arraybuffer'})
.success(function (response) {
var file = new Blob([(response)], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
$scope.content = $sce.trustAsResourceUrl(fileURL);
});
view:
<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>
I faced difficulties using "window.URL" with Opera Browser as it would result to "undefined". Also, with window.URL, the PDF document never opened in Internet Explorer and Microsoft Edge (it would remain waiting forever). I came up with the following solution that works in IE, Edge, Firefox, Chrome and Opera (have not tested with Safari):
$http.post(postUrl, data, {responseType: 'arraybuffer'})
.success(success).error(failed);
function success(data) {
openPDF(data.data, "myPDFdoc.pdf");
};
function failed(error) {...};
function openPDF(resData, fileName) {
var ieEDGE = navigator.userAgent.match(/Edge/g);
var ie = navigator.userAgent.match(/.NET/g); // IE 11+
var oldIE = navigator.userAgent.match(/MSIE/g);
var blob = new window.Blob([resData], { type: 'application/pdf' });
if (ie || oldIE || ieEDGE) {
window.navigator.msSaveBlob(blob, fileName);
}
else {
var reader = new window.FileReader();
reader.onloadend = function () {
window.location.href = reader.result;
};
reader.readAsDataURL(blob);
}
}
Let me know if it helped! :)
Adding responseType to the request that is made from angular is indeed the solution, but for me it didn't work until I've set responseType to blob, not to arrayBuffer. The code is self explanatory:
$http({
method : 'GET',
url : 'api/paperAttachments/download/' + id,
responseType: "blob"
}).then(function successCallback(response) {
console.log(response);
var blob = new Blob([response.data]);
FileSaver.saveAs(blob, getFileNameFromHttpResponse(response));
}, function errorCallback(response) {
});
Most recent answer (for Angular 8+):
this.http.post("your-url",params,{responseType:'arraybuffer' as 'json'}).subscribe(
(res) => {
this.showpdf(res);
}
)};
public Content:SafeResourceUrl;
showpdf(response:ArrayBuffer) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
this.Content = this.sanitizer.bypassSecurityTrustResourceUrl(fileURL);
}
HTML :
<embed [src]="Content" style="width:200px;height:200px;" type="application/pdf" />
I have struggled for the past couple of days trying to download pdfs and images,all I was able to download was simple text files.
Most of the questions have the same components, but it took a while to figure out the right order to make it work.
Thank you #Nikolay Melnikov, your comment/reply to this question was what made it work.
In a nutshell, here is my AngularJS Service backend call:
getDownloadUrl(fileID){
//
//Get the download url of the file
let fullPath = this.paths.downloadServerURL + fileId;
//
// return the file as arraybuffer
return this.$http.get(fullPath, {
headers: {
'Authorization': 'Bearer ' + this.sessionService.getToken()
},
responseType: 'arraybuffer'
});
}
From my controller:
downloadFile(){
myService.getDownloadUrl(idOfTheFile).then( (response) => {
//Create a new blob object
let myBlobObject=new Blob([response.data],{ type:'application/pdf'});
//Ideally the mime type can change based on the file extension
//let myBlobObject=new Blob([response.data],{ type: mimeType});
var url = window.URL || window.webkitURL
var fileURL = url.createObjectURL(myBlobObject);
var downloadLink = angular.element('<a></a>');
downloadLink.attr('href',fileURL);
downloadLink.attr('download',this.myFilesObj[documentId].name);
downloadLink.attr('target','_self');
downloadLink[0].click();//call click function
url.revokeObjectURL(fileURL);//revoke the object from URL
});
}
A suggestion of code that I just used in my project using AngularJS v1.7.2
$http.get('LabelsPDF?ids=' + ids, { responseType: 'arraybuffer' })
.then(function (response) {
var file = new Blob([response.data], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
$scope.ContentPDF = $sce.trustAsResourceUrl(fileURL);
});
<embed ng-src="{{ContentPDF}}" type="application/pdf" class="col-xs-12" style="height:100px; text-align:center;" />

Resources