Angular FIle upload Custom headers for upload all - angularjs

I want to add custom headers to a file before Uploading. Both methods below are not working:
$scope.uploadallman = function (qID) {
alert(qID);
uploader.headers = { QuestionID: qID };
//item.headers = {
// MyHeader: qID,
//};
uploader.uploadAll();
}

Maybe not the best solution, but it's the way I do it and it's working.
function _uploadFile(resourceURL, file) {
var deferred = $q.defer();
var config = {};
config.headers = {};
config.transformRequest = angular.identity;
config.headers['Content-Type'] = undefined;
// config.headers['MyCustomHeaderKey'] = MyCustomHeaderValue; // Optional
var formData = new FormData();
formData.append('file', file);
// formData.append('myCustomFormDataAttributeKey', myCustomFormDataAttributeValue); // Optional
$http.post(resourceURL, formData, config)
.success(function (response) {
deferred.resolve(response);
})
.error(function (err, status) {
deferred.reject(err);
});
return deferred.promise;
}
This is very good topic about the file upload in Angular:
How to POST JSON and a file to web service with Angular?

Related

Pass array of data in angularjs multipart

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.

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) {
})

How to pass $scope variable data into node.js backend server file?

I have json data in $scope variable and i want to use that $scope variable inside my backend app.js node file.
This is my backend file app.js:
app.post('/upload', upload.single('file'), function(req, res) {
var XLSX = require('xlsx');
var workbook = XLSX.readFile('./uploads/' + req.file.filename);
var sheet_name_list = workbook.SheetNames;
var data = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
//var values = [];
console.log(data);
return res.status(200).send(data);
});
app.post('/api/uploadlast',api.addNewContact, function(req,res){
Contact.bulkCreate(excels).then(function(users) {
return res.status(200).send(users);
}).catch(Sequelize.ValidationError, function(err) {
return res.status(422).send(err.errors[0].message);
}).catch(function(err) {
return res.status(400).send(err.message);
});
})
This is my controller file:
$scope.uploadFile = function() {
var file = $scope.myFile;
var uploadUrl = "/upload";
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
})
.then(function(response) {
//$state.reload();
$scope.excels = response.data;
console.log("success!!");
})
.catch(function() {
console.log("error!!");
});
}
$scope.uploadLast = function() {
$http.post('/api/uploadlast').then(function(response) {
$state.reload();
});
}
})
I want to get $scope.excels data into my backend to bulkcreate into databases.
You can pass any data with a post request as the second parameter of $http.post(). So you can do something like:
$scope.uploadLast = function() {
var data = {
excels: $scope.excels
};
$http.post('/api/uploadlast', data).then(function(response) {
$state.reload();
});
}
And in your backend, you can access it like:
app.post('/api/uploadlast',api.addNewContact, function(req, res){
var data = req.body.excels;
Contact.bulkCreate(data).then(function(users) {
return res.status(200).send(users);
}).catch(Sequelize.ValidationError, function(err) {
return res.status(422).send(err.errors[0].message);
}).catch(function(err) {
return res.status(400).send(err.message);
});
});

PUT request to Amazon S3 bucket using presigned url returns 403

I'm getting the presigned url from a Node.js server using aws-sdk. Here is the server code, which always returns a 200 code and a the url:
getSignedUrl: function(req, res, next){
aws.config.update({ accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY });
var s3 = new aws.S3();
var s3_params = {
Bucket: S3_BUCKET,
Key: req.query.file_name,
ContentType: req.query.file_type,
ACL: 'public-read'
};
s3.getSignedUrl('putObject', s3_params, function(err, data){
if (err) {
return next(err);
}
else {
var return_data = {
signed_request: data,
url: 'https://'+S3_BUCKET+'.s3.amazonaws.com/'+req.query.file_name
};
res.json(return_data);
}
});
}
My client-side is Angular. I've uloaded a file using a File Reader service:
.factory('fileReaderFactory', ['$q', '$log', function($q, $log){
....
var getReader = function(deferred, scope) {
var reader = new FileReader();
....
return reader;
};
var readAsDataURL = function (file, scope) {
var deferred = $q.defer();
var reader = getReader(deferred, scope);
scope.$broadcast("fileData", {
name: file.name,
type: file.type
});
reader.readAsDataURL(file);
return deferred.promise;
};
return {
readAsDataUrl: readAsDataURL
};
}]);
My controller:
.controller('UploadCtrl', ['apiFactory','fileReaderFactory','$scope', function(apiFactory, fileReaderFactory, $scope){
$scope.data = {};
$scope.fileData = {};
...
$scope.readFile = function() {
fileReaderFactory.readAsDataUrl($scope.file, $scope)
.then(function(result){
$scope.imgSrc = result;
imgUploaded = true;
});
};
$scope.upload = function(){
apiFactory.getSignedUrl($scope.fileData)
.then(function(result){
return apiFactory.uploadS3(result, $scope.fileData, $scope.imgSrc);
})
.then(function(result){
}, function(error){
console.log(error);
})
};
....
}]);
And finally the snippets of code from the apiFactory:
apiFactory.getSignedUrl = function(data){
return $http({
method: 'GET',
url: API_URL + '/sign_s3',
params : {
"file_name": data.name,
"file_type": data.type,
}
});
};
apiFactory.uploadS3 = function(result, data, file){
return $http({
method: 'PUT',
url: result.data.signed_request,
data: file,
headers: {
"x-amz-acl": "public-read"
}
});
}
I always get a 403: Forbidden back from Amazon when I try to upload the file using the signed url, however.

Angular - Make multiple request on app.run()

On my app, I need to recover data (json) by making multiples validations using http requests before all my app starts. So my problem is that I'm using angular.run() to make all the http requests and resolving all of the validations with promises.
The problem is, not all of my promises are executed before my app is started.
part of my code is:
appModule.run(configRun);
configRun.$inject = [
'$http', '$rootScope', 'gettextCatalog', 'ipLoadDataService',
'webStorageService', 'ipDataSetParserService'];
function configRun($http, $rootScope, gettextCatalog, ipLoadDataSrv, webStrSrv, dataSetParser) {
webStrSrv.clear();
ipLoadDataSrv.getHeadDataSet2()
.then(function (responseHead) {
if (ipLoadDataSrv.updatedDataSet2(responseHead.headers["last-modified"])) {
//save into localstorage
webStrSrv.clear();
webStrSrv.setItem("last-modified", { date: responseHead.headers["last-modified"] });
ipLoadDataSrv.getDataSet2()
.then(function (responseData) {
$rootScope.cabecera = responseData;
})
}
})
}
// LoadDataService
appModule.factory('ipLoadDataService', loadDataService);
loadDataService.$inject = ['$http',
'$q',
'webStorageService',
'myPrjEnvironment',
'ipDataSetParserService'];
function loadDataService($http, $q, webStoreService, myPrj, dataSetParser) {
var eventMap = [];
var ip_loadDataService = {
getHeadDataSet2: getHeadDataSet2,
requestDataSet: requestDataSet,
updatedDataSet2: updatedDataSet2,
getDataSet2: getDataSet2
};
return ip_loadDataService;
function getHeadDataSet2() {
/*HEAD*/
var deferred = $q.defer();
$http.head(myPrj.URL_DATA)
.success(function (data, status, headers, config) {
var response = [];
response.data = data;
response.headers = headers();
deferred.resolve(response);
//return deferred.promise;
}).error(function (data, status) {
deferred.reject(data);
});
return deferred.promise;
}
function getDataSet2() {
return xhr('get', [myPrj.URL_DATA]);
}
function updatedDataSet2(last_date_modified) {
//var self = this;
var dateOnWebStore = webStoreService.getItem("last-modified");
if (dateOnWebStore === null || Date.parse(dateOnWebStore.date) < Date.parse(last_date_modified))
return true;
return false;
}
function xhr(type, config) {
if (!config && angular.isArray(type)) {
config = type;
type = 'get';
}
var deferred = $q.defer();
$http[type].apply($http, config)
.success(function (data, status, headers, config) {
var response = [];
response.data = data;
response.headers = headers();
deferred.resolve(response);
})
.error(function (error) {
deferred.reject(error);
});
return deferred.promise;
}
}
Answering the question in your second post, maybe you better edit your original post with the new issue you encountered.
If what you are looking for is a way to activate a state (home.myPrjMain in your case) you can do this in various ways:
Using JS - use $state.go(). See - $State documentation
Using directive - use the ui-sref directive with the name of the required state. See - ui-sref documentation
Using regular html href (Navigate to url) - with the full address of the state you need. In your case, "/main".
I hope this was helpful
Have the UI start in an initial loading state then use ui-router to wait for the various pieces to resolve before going to the initial state.
Here is a fiddle showing how it works. Fiddle
I did two parts, one with a single fake service call using timeout and a second with a chained set of calls,.
this.slowServiceCall = function(input, delay) {
var deferred = $q.defer();
var workFinished = function () {
deferred.resolve(input);
};
$timeout(workFinished, delay);
return deferred.promise;
};
this.slowChainedServiceCall = function(input, delay) {
var deferred = $q.defer();
var workFinished = function () {
deferred.resolve(input);
};
$timeout(workFinished, delay);
var promiseChain = deferred.promise.then(function(result) {
var deferred2 = $q.defer();
$timeout(function(){
deferred2.resolve(result + ' Second Piece');
},100);
return deferred2.promise;
});
return promiseChain;
};

Resources