I'm working on a Grails (2.3.7) application with AngularJS. I've to upload files in my application. Since the front end is managed by Angular , I'm uploading my file from Angular controller. I've gone through This and this discussions , and tried to upload as follows.
My file uploader is
<input type="file" ng-file-select="onFileSelect($files)">
Angular controller is
myapp.controller('createWebController',['$scope','$http','$upload',function($scope,$http,$upload){
$scope.onFileSelect = function($files) {
var file = $files[0];
console.log(file)
$upload.upload({
url: 'UploadLogo/upload', //upload.php script, node.js route, or servlet url
file: file,
method: 'POST' ,
fileFormDataName: "myFile",
}).progress(function(evt) {
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
})
.error(function(data){ console.log(data)})
;
};
}])
on the server , I'm using this service and the upload handler code is
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.MultipartFile
import org.codehaus.groovy.grails.web.context.ServletContextHolder
class UploadLogoController {
FileUploadService fileUploadService
def upload() {
def avatarImage = request.getFile('file')
if (!avatarImage.isEmpty())
{
userInstance.avatar = fileUploadService.uploadFile(avatarImage, "logo.png", "~/Desktop/upload")
render "ok"
}
else
{
render "Empty"
}
}
}
But the problem is I'm getting a 500 (Internal Server Error)
from grails. The file is not being uploaded.
also getting response as Cannot invoke method isEmpty() on null object
Which means the file has not been sent to the server. Whats the problem here.. Please help..
Try this way. You could create a custom directive for the file upload control
myapp.directive('ngFileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.ngFileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};}])
and in your html use <input type="file" ng-file-model="myFile" />
Then you could create a custom service to do the file upload. Note that its not necessary to create service but it can easily reuse in later file uploads just by injecting the service.
myapp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl,filename){
var fd = new FormData();
fd.append('file', file);
fd.append('filename', filename);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(data){
console.log(data)
})
.error(function(data){ console.log(data)
});
};}]);
The uploadFileToUrl takes 3 arguments , the file itself , the URL to upload and the file name to be saved as.(You can customize this as you wish) . Use the $http.post
to post data.
Finally in your controller , include this
var file = $scope.myFile;
var filename = 'YourFileName'
var uploadUrl = '/UploadLogo/upload' // don't forget to include the leading /
fileUpload.uploadFileToUrl(file, uploadUrl,filename);