0

I am new to Angular JS and trying my hands on File upload. My requirement is to submit the multipart data on button click.

I read on ng-model not working on type="file", so I got to know the work around and i copied the directive. after working through that directive, while sending data there is no Content-disposition data set. I mean file name, content type etc which I want to read at server side. that is why I am getting null at headerOfFilePart.getFileName()

what I am doing wrong. what is the right way to achieve things i described above in Angular JS.

    <div ng-controller="uploadController">  
        <h2> Add Order </h2>
        Enter your Name: 
            <input type="text" name="name" ng-model="myName"/>
            <input type="file" fileread="vm.uploadme" />
            <input type="button" name="button" ng-click='uploadFile()'/>
    </div>

And this is my JS part

validationApp.controller('uploadController', function($scope,$http,$location,$window) {
    $scope.uploadFile = function() {

        var fd = new FormData();
        //Take the first selected file
        fd.append("file", $scope.vm.uploadme);
        fd.append("name", $scope.myName);

        uploadUrl = "http://localhost:8080/IPOCCService/rest/UserManager/upload1";
        $http.post(uploadUrl, fd, {
            withCredentials: true,
            headers: {'Content-Type': undefined },
            transformRequest: angular.identity
        }).
        success(function(data, status, headers, config) {
            alert(data);
        }).
        error(function(data, status, headers, config) {
            alert("failure");
        });

    };
});


validationApp.directive("fileread", [function () {
    return {
        scope: {
            fileread: "="
        },
        link: function (scope, element, attributes) {
            element.bind("change", function (changeEvent) {
                var reader = new FileReader();
                reader.onload = function (loadEvent) {
                    scope.$apply(function () {
                        scope.fileread = loadEvent.target.result;
                    });
                };
                reader.readAsDataURL(changeEvent.target.files[0]);
            });
        }
    };
}]);

REST JAVA

    @POST
    @Path("/upload1")
    @Produces({ MediaType.APPLICATION_JSON} )
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response responseMsg3(FormDataMultiPart form) {
        System.out.println("File Uploaded");

        FormDataBodyPart filePart1 = form.getField("name");
        System.out.println(filePart1.getName() + " = " +filePart1.getValue());

        FormDataBodyPart filePart = form.getField("file");

        ContentDisposition headerOfFilePart =  filePart.getContentDisposition();
        InputStream fileInputStream = filePart.getValueAs(InputStream.class);
        String filePath = SERVER_UPLOAD_LOCATION_FOLDER + headerOfFilePart.getFileName();



        // save the file to the server
        saveFile(fileInputStream, filePath);
        String output = "File saved to server location : " + filePath;
        return Response.status(200).entity("true").build();
    }
Jayesh
  • 6,047
  • 13
  • 49
  • 81

3 Answers3

1

When you use FileReader to read your files, only the contents of the file is assigned to your scope:

scope.fileread = loadEvent.target.result;

In your case, just simply assign the file to your scope:

link: function (scope, element, attributes) {
      element.bind("change", function (changeEvent) {
         scope.$apply(function(){
              scope.fileread = changeEvent.target.files[0];
         // changeEvent.target.files[0] is an HTML5 file object which contains ALL
         // information about the file including fileName, contents,...
         // scope.fileread is now assigned the selected file
         });   
     });
}
Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • Hey Khanh, as I mentioned in my previous comment that I blindly copied the code without understanding what it is doing. can you please point a link where it is explained or can help understanding what the piece of code you mention does line by line. – Jayesh Sep 30 '14 at 12:21
  • @Jayesh: See my updated answer to see if it's clearer – Khanh TO Sep 30 '14 at 12:26
  • 1
    @Jayesh: when you use `FileReader`, you read `only the contents` whereas `changeEvent.target.files[0]` has `all information` including contents, fileName,... – Khanh TO Sep 30 '14 at 12:29
  • Thanks. I got your explanation. what is this line doing, modelSetter(scope, element[0].files[0]); where is modelSetter function declared? – Jayesh Sep 30 '14 at 12:43
  • @Jayesh: You could read https://docs.angularjs.org/api/ng/service/$parse . In this case, I think it's not necessary, just assign to `scope.fileread` directly. – Khanh TO Sep 30 '14 at 12:45
  • @Jayesh: For the $parse service, you can take a look at a good explanation at http://stackoverflow.com/questions/17900588/what-is-the-difference-between-the-parse-interpolate-and-compile-services. In your case, the attribute is bound to your scope, $parse is not necessary, just assign directly to your scope. – Khanh TO Oct 04 '14 at 13:18
0
app.directive('fileRead', ['$parse', function ($parse) {
return {
    restrict: 'A',
    link: function(scope, element, attrs) {
        var model = $parse(attrs.fileread);
        var modelSetter = model.assign;

        element.bind('change', function(){
            function readURL(input) {
                if (input.files && input.files[0]) {
                    var reader = new FileReader();
                    reader.readAsDataURL(input.files[0]);
                }
            }
            readURL(this);
            scope.$apply(function(){
                modelSetter(scope, element[0].files[0]);
            });
        });
    }
};
}]);

<input type="file" file-read="vm.uploadme" />

this directive works for me.

Kalhan.Toress
  • 21,683
  • 8
  • 68
  • 92
  • Thanks ..... it is working... i just copied like a dumb.. doesn't know what it is actually doing. can you please point out the explanation of this directive or can explain please. – Jayesh Sep 30 '14 at 09:49
  • why do you need to use `readURL`? I don't see the difference if we move this. – Khanh TO Sep 30 '14 at 09:55
  • Hey Khanh, as I mentioned in my previous comment that I blindly copied the code without understanding what it is doing. can you please point a link where it is explained or can help understanding what the piece of code you mention does line by line. – Jayesh Sep 30 '14 at 12:21
  • @Jayesh: A mistake I mean remove, not move: why do you need to use `readURL`? I don't see the difference if we remove this. – Khanh TO Oct 04 '14 at 13:22
0

You can use the module ng-file-upload it's a directive that do everythinh about file upload See here

Mathieu Bertin
  • 1,634
  • 11
  • 11