DNRN
DNRN

Reputation: 2489

Adding image to AngularJS model for upload

I am new to this wonderful framework AngularJS. I have a C# API controller where I would like to upload data from a form that includes an image. Normally (razor) I would upload a form as json and include the image as a HttpPostedFileBase:

public ArtWork SaveArtWork(ArtWork artWork, HttpPostedFileBase file)
    { // save in db and return object }

I have found a lot of different ways for uploading the file wrapped in a FormData object ([AngularJS Uploading An Image With ng-upload):

$scope.uploadFile = function(files) {
var fd = new FormData();
//Take the first selected file
fd.append("file", files[0]);

$http.post(uploadUrl, fd, {
    withCredentials: true,
    headers: {'Content-Type': undefined },
    transformRequest: angular.identity
}).success( ...all right!... ).error( ..damn!... );
};

But I have some other properties I have parsed to a json object, and now I would like to upload it all in a bundle. Or is it possible to get the image data as a base64 and add it to my json object? I know that a base64 is 1/3 bigger than a byte stream, but it's so easy to work with :)

Here's my Angular Controller:

'use strict';

(function () {

// Factory
angular.module('umbraco').factory('artworkResource', function ($http) {
    return {
        getById: function (id) {
            return $http.get("backoffice/Trapholt/ArtWorkApi/GetById/" + id);
        },
        save: function (artwork) {
            return $http.post("backoffice/Trapholt/ArtWorkApi/SaveArtWork", angular.toJson(artwork));
        },
        save2: function (artwork, fd) {
        return $http.post("backoffice/Trapholt/ArtWorkApi/SaveArtWork", angular.toJson(artwork), fd);
    }
    };
});

// Controller
function artworkController($scope, $routeParams, artworkResource, $http) {

    $scope.categories = ['Keramik', 'Maleri', 'Møbel', 'Skulptur'];

    artworkResource.getById($routeParams.id).then(function (response) {
        $scope.curatorSubject = response.data;
    });


    var fd;
    $scope.uploadFile = function(files) {
        fd = new FormData();
        fd.append("file", files[0]);
    };

    $scope.save = function (artwork) {
        artworkResource.save(artwork, fd).then(function (response) {
            $scope.artwork = response.data;

            alert("Success", artwork.Title + " er gemt");
        });
    };


};
//register the controller
angular.module("umbraco").controller('ArtworkTree.EditController', artworkController);

})();

So how can I combine my image and the other properties in one json object or two arguments? Please leave a comment if I need to explain some more, any help would really be appreciated :)

Upvotes: 1

Views: 3524

Answers (1)

DNRN
DNRN

Reputation: 2489

I found a solution, where I added the file and the model to the form data. So it was actually pretty easy to expand solution from here. This is my Angular controller:

function artworkController($scope, $routeParams, artworkResource, $http) {

    $scope.categories = ['Keramik', 'Maleri', 'Møbel', 'Skulptur'];

    artworkResource.getById($routeParams.id).then(function (response) {
        $scope.curatorSubject = response.data;
    });


    var fd;
    $scope.uploadFile = function(files) {
        fd = new FormData();
        fd.append("file", files[0]);
    };

    $scope.save = function (artwork) {

        fd.append("ArtWork", angular.toJson(artwork));

        $http.post("backoffice/Trapholt/ArtWorkApi/Post", fd, {
            transformRequest: angular.identity,
            headers: { 'Content-Type': undefined }
        });
    };


};

And this i my C# mvc API controller:

public HttpResponseMessage Post()
    {
        HttpResponseMessage result = null;
        var httpRequest = HttpContext.Current.Request;
        if (httpRequest.Files.Count > 0)
        {
            var file = httpRequest.Files[0];
            var artworkjson = httpRequest.Form[0];
            var artwork = JsonConvert.DeserializeObject<ArtWork>(artworkjson);
            if (artwork == null)
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest, "No saved");
            }

            using (var binaryReader = new BinaryReader(file.InputStream))
            {
                artwork.Picture = binaryReader.ReadBytes(file.ContentLength);
            }

            result = Request.CreateResponse(HttpStatusCode.Created, "ok");
        }
        else
        {
            result = Request.CreateResponse(HttpStatusCode.BadRequest);
        }
        return result;
    }

The html view is a normal form where all the inputs are bound with the model, expect the file input field:

<input type="file" id="file" name="picture" onchange="angular.element(this).scope().uploadFile(this.files)"/>

Upvotes: 2

Related Questions