sending files via POST with AngularJS - angularjs

I have a problem sending data via POST in angular,
my data include 2 files and some text field,
the problem is that the service doesn't receives any data.
this is my code:
var inputs = document.querySelectorAll( 'input[type="file"]' );
Array.prototype.forEach.call( inputs, function( input ){
input.addEventListener( 'change', function( e ){
if(this.id == "zipToUpload")
$scope.zipToUpload = this.files[0];
else
$scope.imgToUpload = this.files[1];
});
});
$scope.submit = function(){
var getInput = {nome: $scope.app_name, zipToUpload: $scope.zipToUpload, imgToUpload: $scope.imgToUpload, url: $scope.app_url,
secure: $scope.checkbox_pass, hide: $scope.checkbox_hide, beta: $scope.checkbox_beta, password: $scope.app_pass, location: "1" };
var req = {
method: 'POST',
url: 'api/rest/app/insert_app.php',
headers: {
'Content-Type': undefined
},
data: getInput
}
$http(req)
.then(function(result) {
console.log(result);
});
}

You can not directly upload file using model in angular. First you need a directive to bind files to the model.
myApp.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
And the input will be like :
<input type = "file" file-model = "myFile"/>
And the you can send post request using form data
$scope.upload = funtion(){
var fd = new FormData();
fd.append('file', $scope.myFile);
var req = {
method: 'POST',
url: 'api/rest/app/insert_app.php',
headers: {
'Content-Type': undefined
},
data: fd
}
$http(req)
.then(function(result) {
console.log(result);
});
}

Related

File upload in angularjs with code igniter

What I am trying to do is to upload excel file using angular and codeigniter .
But the problem is when I am am uploading it is not been accepted by the CI function ,Status code is 200 when I am sending but I am getting empty array when I am printing
print_r($_POST); print_r($_FILES);
Here is my service:
function UploadExcel(file,uploadUrl) {
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': 'multipart/form-data'},
})
.success(function(){
})
.error(function(){
});
Here is my directive
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
Here is my Controller
$scope.ImportApplicant = function() {
var file = $scope.myFile;
var uploadUrl = 'user/fileUpload';
UserService.UploadExcel(file, uploadUrl);
}
For angular code
$scope.setFile1 = function(element)
{
$scope.currentFile = element.files[0];
var t = element.files[0].name;
var vali = t.split('.');
var length = vali.length-1;
var final = vali[length];
if(final=='txt' || final=='pdf' || final=='doc' || final=='docs')
{
var reader = new FileReader();
reader.onload = function(event)
{
$scope.missing.image = event.target.result
$scope.$apply();
$("#image_show").show();
}
reader.readAsDataURL(element.files[0]);
}
}
Codeigniter
$base64_string=$data['profile_image'];
if (preg_match('/base64/i', $base64_string))
{
$randomfile=time().'.jpeg';
$filename='./uploads/users/'.$randomfile;
$this->Cashback_model->base64_to_jpeg($base64_string, $filename);
}
else {
$file_name = explode('/', $base64_string);
foreach ($file_name as $keyval) {
$randomfile = $keyval;
}
}
model
public function base64_to_jpeg($base64_string,$output_file) {
$ifp = fopen($output_file, "wb");
$data = explode(',', $base64_string);
fwrite($ifp, base64_decode($data[1]));
fclose($ifp);
return $output_file;
}

Connection terminated parsing multipart data in Angulrjs and JAX-RS

I wish to send my localhost (in spring boot server) a selected image from the user using AngularJS and add data object in BD using JAX-RS.
-Code HTML:
<form role="form" enctype="multipart/form-data" name="myForm" ng-submit="uploadfile()">
<label class="control-label">Image:</label>
<input type="file" class="form-control " file-model="Image" >
<input type="text" class="form-control " ng-model="name" >
<input type="text" class="form-control " ng-model="lastname" >
<button type="submit"> save</button>
</form>
--code AngularJS;
var app = angular.module('Mainapp', ['ngRoute','file-model','ui.bootstrap']);
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
app.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
//fd.append('file', file);
angular.forEach(file, function(file) {
fd.append('file', file);
});
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function(response) {
console.log("done post "+response);
}).catch(function(e) {
console.log('failed to post: ', e);
throw e;
})
}
}]);
//upload file and data object of user
$scope.uploadfile = function() {
var file = $scope.Image;
console.dir(file);
var uploadUrl ="http://localhost:8000/auditconfig/images/"+file.name;
fileUpload.uploadFileToUrl(file, uploadUrl); // error here "failed to post"
var user = {
name: $scope.name,
lastname: $scope.lastname,
image:file.name
};
$http.post(url+"/add", user) //The user is added to the database
.success(function(data) {
$scope.ListUsers = data;
}).error(function(err, data) {
console.log("error: " +data);
});
};
-After a test of the "uploadfile ()", I get the following results:
//**console.dir(file);
*File:
lastModified:1490260924299
lastModifiedDate; Thu Mar 23 2017 10:22:04 GMT+0100 (Paris, Madrid)
name:"01.png"
size:1637
type:"image/png"
webkitRelativePath:""
__proto__:File
-Test of upload file:
//**console.log('failed to post: ', e);
Failed to load resource: the server responded with a status of 500 (Internal Server Error) :8099/AuditConf/images/01.png
failed to post: Object
Config:Objectd
ata:FormData
__proto__:FormData
headers:Object
Accept:"application/json, text/plain, */*"
Content-Type:undefined
__proto__:Object
method:"POST"
transformRequest:function identity($)
transformResponse:Array(1)
url:"http://localhost:8099/AuditConf/images/Exception--JAX-RS.png"
__proto__:Object
data:Object
error:"Internal Server Error"
exception:"java.lang.RuntimeException"
message:"java.io.IOException: UT000036: Connection terminated parsing multipart data"
path:"/auditconfig/images/Exception--JAX-RS.png"
status:500
timestamp:1490778930961
__proto__:Object
headers:function (name)
status:500 statusText
:"Internal Server Error"
__proto__;Object
The solution is:
var app = angular.module('Mainapp', ['ngRoute','file-model','ui.bootstrap']);
app.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
this.uploadFileToUrl = function(file, uploadUrl){
var data = new FormData();
data.append('file', file);
return $http.post(uploadUrl, data, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).then(function (results) {
return results;
});
}
//upload file and data object of user
$scope.uploadfile = function() {
var file = $scope.Image;
console.dir(file);
//URL of API not path of floder
var uploadUrl ="http://localhost:8000/auditconfig/UpFile";
fileUpload.uploadFileToUrl(file, uploadUrl);
var user = {
name: $scope.name,
lastname: $scope.lastname,
image:file.name
};
$http.post(url+"/add", user)
.success(function(data) {
$scope.ListUsers = data;
}).error(function(err, data) {
console.log("error: " +data);
});
};
Try this:
this.uploadFileToUrl = function(file, uploadUrl){
var data = new FormData();
data.append('file', file);
//Comment below
//angular.forEach(file, function(file) {
// fd.append('file', file);
//});
return $http.post(uploadUrl, data, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).then(function (results) {
return results;
});
}
See the answers here which accepts multiple files within one object 'file'.

Send some additional parameters with FormData in angularjs

Im trying to find a way to upload some parameters along with a file using FormData but not sure where to look for it on the backend.
HTML:
<input type="file" file-model="myFile"/>
<button class="btn" ng-click="uploadFile()">upload</button>
Directive:
.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}])
Controller:
var file = $scope.aFile;
var foo = 'bar';
var fd = new FormData();
fd.append('file', file);
fd.append('foo', foo);
$http.post(api, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function(res){
console.log(res.data);
});
Backend:
$_POST = json_decode(file_get_contents('php://input'),true);
$result = saveFile('./img/', 'a_test_file'); /* SUCCEEDS! */
$res = array($_POST, $_FILES, $result); /* $_POST empty, $_FILES ok, $result success */
/* where is foo?? */
Not sure what Im missing or where to look for the additional parameter?

Send FormData with other field in AngularJS

I have a form with two input text and one upload. I have to send it to the server but I have some problem concatenating the file with the text. The server expects this answer:
"title=first_input" "text=second_input" "file=my_file.pdf"
This is the html:
<input type="text" ng-model="title">
<input type="text" ng-model="text">
<input type="file" file-model="myFile"/>
<button ng-click="send()">
This is the Controller:
$scope.title = null;
$scope.text = null;
$scope.send = function(){
var file = $scope.myFile;
var uploadUrl = 'my_url';
blockUI.start();
Add.uploadFileToUrl(file, $scope.newPost.title, $scope.newPost.text, uploadUrl);
};
This is the Directive fileModel:
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
And this is the Service which call the server:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var fd = new FormData();
fd.append('file', file);
var obj = {
title: title,
text: text,
file: fd
};
var newObj = JSON.stringify(obj);
$http.post(uploadUrl, newObj, {
transformRequest: angular.identity,
headers: {'Content-Type': 'multipart/form-data'}
})
.success(function(){
blockUI.stop();
})
.error(function(error){
toaster.pop('error', 'Errore', error);
});
}
If I try to send, I get Error 400, and the response is: Multipart form parse error - Invalid boundary in multipart: None.
The Payload of Request is: {"title":"sadf","text":"sdfsadf","file":{}}
Don't serialize FormData with POSTing to server. Do this:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var payload = new FormData();
payload.append("title", title);
payload.append('text', text);
payload.append('file', file);
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 use it:
MyService.uploadFileToUrl(file, title, text, uploadUrl).then(successCallback).catch(errorCallback);
Here is the complete solution
html code,
create the text anf file upload fields as shown below
<div class="form-group">
<div>
<label for="usr">User Name:</label>
<input type="text" id="usr" ng-model="model.username">
</div>
<div>
<label for="pwd">Password:</label>
<input type="password" id="pwd" ng-model="model.password">
</div><hr>
<div>
<div class="col-lg-6">
<input type="file" file-model="model.somefile"/>
</div>
</div>
<div>
<label for="dob">Dob:</label>
<input type="date" id="dob" ng-model="model.dob">
</div>
<div>
<label for="email">Email:</label>
<input type="email"id="email" ng-model="model.email">
</div>
<button type="submit" ng-click="saveData(model)" >Submit</button>
directive code
create a filemodel directive to parse file
.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};}]);
Service code
append the file and fields to form data and do $http.post as shown below
remember to keep 'Content-Type': undefined
.service('fileUploadService', ['$http', function ($http) {
this.uploadFileToUrl = function(file, username, password, dob, email, uploadUrl){
var myFormData = new FormData();
myFormData.append('file', file);
myFormData.append('username', username);
myFormData.append('password', password);
myFormData.append('dob', dob);
myFormData.append('email', email);
$http.post(uploadUrl, myFormData, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
}
}]);
In controller
Now in controller call the service by sending required data to be appended in parameters,
$scope.saveData = function(model){
var file = model.myFile;
var uploadUrl = "/api/createUsers";
fileUpload.uploadFileToUrl(file, model.username, model.password, model.dob, model.email, uploadUrl);
};
You're sending JSON-formatted data to a server which isn't expecting that format. You already provided the format that the server needs, so you'll need to format it yourself which is pretty simple.
var data = '"title='+title+'" "text='+text+'" "file='+file+'"';
$http.post(uploadUrl, data)
This never gonna work, you can't stringify your FormData object.
You should do this:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var fd = new FormData();
fd.append('title', title);
fd.append('text', text);
fd.append('file', file);
$http.post(uploadUrl, obj, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
blockUI.stop();
})
.error(function(error){
toaster.pop('error', 'Errore', error);
});
}
Using $resource in AngularJS you can do:
task.service.js
$ngTask.factory("$taskService", [
"$resource",
function ($resource) {
var taskModelUrl = 'api/task/';
return {
rest: {
taskUpload: $resource(taskModelUrl, {
id: '#id'
}, {
save: {
method: "POST",
isArray: false,
headers: {"Content-Type": undefined},
transformRequest: angular.identity
}
})
}
};
}
]);
And then use it in a module:
task.module.js
$ngModelTask.controller("taskController", [
"$scope",
"$taskService",
function (
$scope,
$taskService,
) {
$scope.saveTask = function (name, file) {
var newTask,
payload = new FormData();
payload.append("name", name);
payload.append("file", file);
newTask = $taskService.rest.taskUpload.save(payload);
// check if exists
}
}
Assume that we want to get a list of certain images from a PHP server using the POST method.
You have to provide two parameters in the form for the POST method. Here is how you are going to do.
app.controller('gallery-item', function ($scope, $http) {
var url = 'service.php';
var data = new FormData();
data.append("function", 'getImageList');
data.append('dir', 'all');
$http.post(url, data, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function (response) {
// This function handles success
console.log('angular:', response);
}, function (response) {
// this function handles error
});
});
I have tested it on my system and it works.

net::ERR_INVALID_URL when setting <img> src from $http.get result

I have a angular directive that works on img tags and loads the image dynamically as a base64 string. I use $http.get to load the image and set it into the img.src like this:
var onSuccess = function(response) {
var data = response.data;
element.attr("src", "data:image/png;base64," + data);
};
var onError = function(response) {
console.log("failed to load image");
};
scope.$watch('authSrc', function(newValue) {
if (newValue) {
$http({
method: "GET",
url: scope.authSrc,
data: ""
}).then(onSuccess, onError)
}
});
after i set the src attribute, i get the net::ERR_INVALID_URL error.
The string that returns from the request looks like this:
IHDR����^tiDOT#(##AMȯz�#IDATx��uw\�ٷ�o����G�B["...
Any ideas?
thanks
Got it to work will the help of This link.
Trick was to use responseType: "blob", and use URL/webkitURL createObjectURL()
Here's the full directive:
'use strict';
app.directive('authSrc',function ($http) {
return {
restrict: 'A',
scope: {
authSrc: "="
},
link: function (scope, element) {
var onSuccess = function(response) {
var data = response.data;
var url = window.URL || window.webkitURL;
var src = url.createObjectURL(data);
element.attr("src", src);
};
var onError = function(response) {
console.log("failed to load image");
};
scope.$watch('authSrc', function(newValue) {
if (newValue) {
$http({
method: "GET",
url: scope.authSrc,
responseType: "blob"
}).then(onSuccess, onError)
}
});
}
}
});
Specify the responseType in your request, and you may have to disable default transforms that $http attempts on the data.
see here
My problem was specifying a zoom level after the base64 string '#zoom=90'

Resources