8

The following code for texture upload was working in angularjs 1.2.26 but stopped working when I upgraded my web application to 1.3.0.

HTML Code

<input file-model="file" name="file" type="file">

fileModel 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]);
                });
            });

            scope.$on("reset", function() {
                element.val(null);
            });

        }
    };
} ]);

Upload Function - In 1.2.26 choosing "multipart/form-data" as Content-Type would not work. But with "undefined" as Content-Type angular would do some kind of magic that would make it work.

var upload = function(textureUploadUrl) {
        var formData = new FormData();
        formData.append('name', $scope.name);
        formData.append('file', $scope.file);

        $http.post(textureUploadUrl, formData, {
            transformRequest : angular.identity,
            headers : {
                'Content-Type' : undefined
            }
        }).success(function(uploadedTexture) {
            console.log(uploadedTexture);

            // further processing of uploadedTexture
        });
}

ERROR:

SyntaxError: Unexpected token h
    at Object.parse (native)
    at fromJson (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:1104:14)
    at defaultHttpResponseTransform (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:8572:18)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:8517:12
    at forEach (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:335:20)
    at transformData (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:8516:3)
    at transformResponse (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:9224:23)
    at processQueue (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:12914:27)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:12930:27
    at Scope.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.js:14123:28) 

Does anyone know how to get this working in the new version?

UPDATE

I've narrowed down the problem a little bit. It does not work with 1.3.0-rc.5, but with the previous version (rc.4) it does work. So, I'm currently trying to figure out which changes lead to my problem. Here is the changelog.

1 Answer 1

14

The problem was in the response header of my texture upload request on server side. For building my application I used Spring MVC and had a request mapping like that, but without the produces specification:

@RequestMapping(value = "/uploadUrl", method = RequestMethod.POST, produces = "text/plain; charset=utf-8")
@ResponseBody
public String textureUploadPOST(HttpServletRequest req) {
    // upload texture and create serveUrl for the texture
    return serveUrl;
}

So, without specifying text/plain as Content-Type, Spring automatically uses application/json as Content-Type. And this causes angular.js to invoke JSON.parse since 1.3.0-rc.5 (change). My texture upload returns an URL pointing to the location where the image is served. Because this is a plain String, it resulted in the described error message. So, don't forget to specify correct Content-Types in your server responses :-)

Sign up to request clarification or add additional context in comments.

3 Comments

+1. I had excatly the scenario (file upload returning url) but with jersey instead of spring MVC. The same solution works, i annotate my resource with the jersey equivalent: @Produces(TEXT_PLAIN). You saved me a lot of time.
Glad to hear that! At first I thought it had to do with the upload itself, but it turned out it was a problem with the response.
Note that the problem appears when i upgrade from angular 1.2 to 1.3.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.