I'm trying to implement a simple file upload function using AngularJs and Spring RESTful web services.
HTML
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>File Upload Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="js/myuploadfunction.js"></script>
</head>
<body ng-app="myAp">
<h1>File Upload</h1>
<div ng-controller = "myCtrl">
<input type="file" file-model="myFile"/>
<button ng-click="uploadFile()">upload me</button>
</div>
</body>
</html>
JS
var myApp = angular.module('myAp', []);
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]);
});
});
}
};
}]);
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
}
}]);
myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
$scope.uploadFile = function(){
var file = $scope.myFile;
console.log('file is ' );
console.dir(file);
var uploadUrl = "upload";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
REST
#RequestMapping(value="/upload", method = RequestMethod.POST)
public #ResponseBody void upload(#RequestBody MultipartFile file) {
System.out.println(file.getName());
}
When I run, I get this - POST http://localhost:8080/File/upload 404 (Not Found).
I'm following http://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs for script reference. Any help on this?
As far as I remember, I used MultipartFile as a #RequestParam not a #RequestBody
and the name should match the <input> tag's "name" attribute.
see http://spring.io/guides/gs/uploading-files/
Related
Our team is developing in ServiceNow and created a table widget that needs the ability to upload files per row. Our code for the file upload consist of the following code:
In our controller, we have the following:
$scope.uploadFile = function(){
var file = $scope.myFile;
console.log('file is ' );
console.dir(file);
var uploadUrl = "/fileUpload";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
We also created a dependency called fileUpload:
var myApp = angular.module('myApp', []);
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
};
}]);
Finally, we have an angular provider called fileModel:
function fileModel($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);
});
});
}
};
}
The issue we're running into is when we contain the following within <td> tags:
<input type="file" file-model="myFile"/>
<button ng-click="uploadFile()">upload me</button>
When the above code is out side of the <td> tags, we are able to view the attached files in our console:
Once the <input> is contained within <td>, myFile does not exist in the console. What do we need to do in order for each row of our table to have its own attachments? This is what our table looks like:
Hello Below is the code that I am using and it throws an error :
<!DOCTYPE html>
<html>
<head>
<title>AngularJS File Upoad Example with $http and FormData</title>
<script src="Scripts/jquery.js"></script>
<script src="http://xxxxxxxxxxx/angular.min.js" type="text/javascript"></script>
<script>
var myApp = angular.module('myApp', []);
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]);
});
});
}
};
}]);
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function (file, uploadUrl) {
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
})
.success(function () {
alert("success");
})
.error(function () {
alert("error");
});
}
}]);
myApp.controller('myCtrl', ['$scope', 'fileUpload', function ($scope, fileUpload) {
$scope.uploadFile = function () {
var file = $scope.myFile;
alert(file);
var uploadUrl = "http://xxxxx/listdata.svc/Documents(2)";//linke to the sharepoint document library with item id 2
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
upload me
I followed this tutorial to image upload for ionic app.
https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs
It works but I have one issue: in the file upload, I am returning the new filename from the server. I have to save it to a variable in the controller. I can't save the value from services to controller.
Here is my controller, services and views
Directive & Service
.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('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(data){
alert(data);
})
.error(function(){
});
}
}])
Controller
.controller('MyCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
$scope.uploadBtn1 = false;
$scope.uploadSpin1 = true;
$scope.uploadFile = function(){
var file = $scope.myFile;
$scope.uploadBtn1 = true;
$scope.uploadSpin1 = false;
console.log('file is ' + JSON.stringify(file));
var uploadUrl = "http://example.com/app/upload.php";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
HTML
<input type="file" file-model="myFile"/>
<button type="button" ng-click="uploadFile()"
ng-hide="uploadBtn1" class="ng-hide">upload me</button>
<ion-spinner icon="ios-small" ng-hide="uploadSpin1" class="ng-hide"></ion-spinner>
I also added the loading spinner when the upload starts and I want to hide it when the upload ends.
Thanks
I have made a few changes to the example in question. The service is now implemented as a factory which returns a promise.
You can then wait in your controller for the promise to return and then handle the data in your controller.
codepen example
var uploadFile = fileUpload.uploadFileToUrl(file, uploadUrl);
uploadFile.error(function(data){
alert('data returned - handle me', data);
});
In my example, I have changed the returned data to a string and passed this back to the controller which then alerts the user of this data.
I try to upload a file using Angularjs but ends up with error
<!DOCTYPE html>
<html ng-app = "myApp">
<body>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<div ng-controller = "myCtrl">
<input type="file" file-model="myFile"/>
<button ng-click="uploadFile()">upload me</button>
</div>
<script>
var myApp = angular.module('myApp', []);
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]);
});
});
}
};
}]);
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
}
}]);
myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
$scope.uploadFile = function(){
var file = $scope.myFile;
console.log('file is ' + JSON.stringify(file));
var uploadUrl = "E:\Backup";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
</script>
</body>
</html>
When i run the above code I got the following error
file is {"webkitRelativePath":"","lastModifiedDate":"2014-04-10T13:01:34.000Z","name":"gvxgfg.txt","type":"text/plain","size":95912} test.html:48
XMLHttpRequest cannot load file:///E:/Backup. Cross origin requests are only supported for HTTP. angular.js:8165
Error: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'file:///E:/Backup'.
at Error (native)
at b (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:76:389)
at t (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:72:120)
at $get.h (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:70:91)
at l.promise.then.H (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:97:5)
at l.promise.then.H (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:97:5)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:98:173
at h.$get.h.$eval (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:108:40)
at h.$get.h.$digest (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:105:331)
at h.$get.h.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js:108:370)
I am just a beginner. I dont know where i went wrong. Hope some one resolves. Thanks in Advance
i'm trying to upload image file along with it's details information with AngularJS. The file's details will be stored in JSON file on the server. But, it doesn't work. the return info from the server is just an empty array. I have no idea why my code doesn't work. I to experiment with Content-type, etc, etc... but still no luck.
my code:
<body>
<div>
<form ng-controller="Ctrl" ng-submit="save()">
Title :<input type="text" ng-model="file_details.title"><br>
Summary: <input type="text" ng-model="file_details.summary"><br>
File: <input type="file" file-upload><br>
<button type="submit">save</button>
</form>
</div>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script src="bower_components/angular/angular.min.js"></script>
<script>
//Angular here
(function(){
var app = angular.module('myApp', []);
app.config(function($httpProvider){
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
app.controller('Ctrl', ['$scope', '$http', function($scope, $http){
$scope.file_details = {};
$scope.files = [];
//listening from fileUpload directive
$scope.$on('fileSelected', function(event, args){
$scope.$apply(function(){
//add the file object to scope's files collection
$scope.files.push(args.file);
});
});
$scope.save = function(){
$http({
method: 'POST',
url: 'process.php',
transformRequest: function (data) {
var formData = new FormData();
formData.append("file_details", angular.toJson(data.file_details));
formData.append("file", data.files);
},
headers: {
'Content-Type': false
},
data: {
file_details: $scope.file_details,
files: $scope.files
}
}).success(function (data, status, headers, config) {
// alert("success!");
console.log(data);
});
}
}]);
app.directive('fileUpload', function(){
return{
link: function(scope, elm, attrs){
elm.bind('change', function(event){
var files = event.target.files;
scope.$emit('fileSelected', { file: files });
});
}
}
});
})();
</script>
</body>
My server code (just to check if the data is sent, but it still returning an empty array):
print_r($_POST); die();