- 
      
 - 
        
Save cssquirrel/3e5daad14bd2ff40edcc to your computer and use it in GitHub Desktop.  
| // The Angular service that will handle the API call to initialize the file upload to the server. | |
| (function (app) { | |
| var fileApiService = function ($http) { | |
| var fileApiFactory = {}; | |
| /** | |
| * @ngdoc method | |
| * @name importFile | |
| * @function | |
| * | |
| * @param {file} file - File object acquired via File Upload API. | |
| * @description - Upload a file to the server. | |
| */ | |
| fileApiFactory.uploadFileToServer = function (file) { | |
| var request = { | |
| file: file | |
| }; | |
| return $http({ | |
| method: 'POST', | |
| url: "/umbraco/api/FileUploadApi/UploadFileToServer", | |
| // If using Angular version <1.3, use Content-Type: false. | |
| // Otherwise, use Content-Type: undefined | |
| headers: { 'Content-Type': undefined }, | |
| transformRequest: function (data) { | |
| var formData = new FormData(); | |
| formData.append("file", data.file); | |
| return formData; | |
| }, | |
| data: request | |
| }).then(function (response) { | |
| if (response) { | |
| var fileName = response.data; | |
| return fileName; | |
| } else { | |
| return false; | |
| } | |
| }); | |
| }; | |
| return fileApiFactory; | |
| }; | |
| app.factory('fileApiService', fileApiService); | |
| }(angular.module(appName))); | 
| // The Angular controller to bind to your view. | |
| (function (app) { | |
| var fileUploadController = function ($scope, fileApiService) { | |
| /*------------------------------------------------------------------- | |
| * Initialization Methods | |
| * ------------------------------------------------------------------*/ | |
| /** | |
| * @ngdoc method | |
| * @name init | |
| * @function | |
| * | |
| * @description - Called when the $scope is initalized. | |
| */ | |
| $scope.init = function () { | |
| $scope.setVariables(); | |
| }; | |
| /** | |
| * @ngdoc method | |
| * @name setVariables | |
| * @function | |
| * | |
| * @description - Sets the initial states of the $scope variables. | |
| */ | |
| $scope.setVariables = function () { | |
| $scope.file = false; | |
| $scope.isUploading = false; | |
| }; | |
| /*------------------------------------------------------------------- | |
| * Event Handler Methods | |
| *-------------------------------------------------------------------*/ | |
| /** | |
| * @ngdoc method | |
| * @name fileSelected | |
| * @function | |
| * | |
| * @param {array of file} files - One or more files selected by the HTML5 File Upload API. | |
| * @description - Get the file selected and store it in scope. This current example restricts the upload to a single file, so only take the first. | |
| */ | |
| $scope.acceptSelectedFile = function (files) { | |
| if (files.length > 0) { | |
| $scope.file = files[0]; | |
| } | |
| }; | |
| /*------------------------------------------------------------------- | |
| * Helper Methods | |
| * ------------------------------------------------------------------*/ | |
| /** | |
| * @ngdoc method | |
| * @name uploadFile | |
| * @function | |
| * | |
| * @description - Uploads a file to the backend. | |
| */ | |
| $scope.uploadFile = function () { | |
| if (!$scope.isUploading) { | |
| if ($scope.file) { | |
| $scope.isUploading = true; | |
| var promise = fileApiService.uploadFileToServer($scope.file); | |
| promise.then(function (response) { | |
| if (response) { | |
| console.info('Saved to server with the filename ' + response); | |
| } | |
| $scope.isUploading = false; | |
| }, function (reason) { | |
| console.info("File import failed."); | |
| console.info(reason.message); | |
| $scope.isUploading = false; | |
| }); | |
| } else { | |
| console.info("Must select a file to import."); | |
| $scope.isUploading = false; | |
| } | |
| } | |
| }; | |
| /*-------------------------------------------------------------------*/ | |
| $scope.init(); | |
| }; | |
| app.controller('FileUploadController', ['$scope', 'fileApiService', fileUploadController]); | |
| }(angular.module(appName))); | 
| <!DOCTYPE html> | |
| <head> | |
| <title>File Upload</title> | |
| </head> | |
| <body> | |
| <!-- Example view to bind to your Angular --> | |
| <div id="content" data-ng-app="exampleApp" data-ng-controller="FileUploadController"> | |
| <h1>Upload a file</h1> | |
| <!-- using ng-file-upload by Danial Farid --> | |
| <!-- See for https://github.com/danialfarid/ng-file-upload documentation on configuration --> | |
| <button ng-file-select ng-model="files" ng-file-change="fileSelected(files)" class="file button btn-primary" ng-multiple="false" accept=".jpg,.png,.gif" ng-show="!isUploading"> | |
| Choose File | |
| </button> | |
| <button type="button" data-ng-click="uploadFile()">Upload</button> | |
| </div> | |
| <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> | |
| <!-- the ng-file-upload directive by Danial Farid https://github.com/danialfarid/ng-file-upload --> | |
| <script src="angular-file-upload.js"></script> | |
| <script src="ng.app.js"></script> | |
| <script src="file.upload.api.service.js"></script> | |
| <script src="file.upload.controller.js"></script> | |
| </body> | |
| </html> | 
| // Use whatever namespacing works for your project. | |
| namespace YourSite.Web.Controllers.Api | |
| { | |
| using System.IO; | |
| using System.Linq; | |
| using System.Net; | |
| using System.Net.Http; | |
| using System.Threading.Tasks; | |
| using System.Web; | |
| using System.Web.Http; | |
| using Umbraco.Web.WebApi; | |
| // If you want this endpoint to only be accessible when the user is logged in, | |
| // then use UmbracoAuthorizedApiController instead of UmbracoApiController | |
| public class FileUploadApiController : UmbracoApiController | |
| { | |
| public async Task<HttpResponseMessage> UploadFileToServer() | |
| { | |
| if (!Request.Content.IsMimeMultipartContent()) | |
| { | |
| throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); | |
| } | |
| // Make this directory whatever makes sense for your project. | |
| var root = HttpContext.Current.Server.MapPath("~/App_Data/Temp/FileUploads"); | |
| Directory.CreateDirectory(root); | |
| var provider = new MultipartFormDataStreamProvider(root); | |
| var result = await Request.Content.ReadAsMultipartAsync(provider); | |
| // Build a list of the filenames of the files saved from your upload, to return to sender. | |
| var fileName = result.FileData.Aggregate(string.Empty, (current, file) => current + ("," + file.LocalFileName)); | |
| return Request.CreateResponse(HttpStatusCode.OK, fileName); | |
| } | |
| } | |
| } | 
| // Example Angular app declaration. | |
| // This example makes use of the ng-file-upload directive by Danial Farid https://github.com/danialfarid/ng-file-upload | |
| // It needs to be injected into the Angular app. | |
| // You could probably use the native HTML5 file upload API if you didn't want to rely on any external directives. | |
| var appName = 'exampleApp'; | |
| (function () { | |
| var app = angular.module(appName, ['angularFileUpload']); | |
| }()); | 
May or may not be of interest, but instead of using the Aggregate function I got the file name(s) like so and send them back as a piped string (I append the extension if it's missing).
        // Build a list of the filenames of the files saved from your upload, to return to sender.
        var fileList = new List<string>();
        foreach (var file in result.FileData)
        {
            var fileName = file.Headers.ContentDisposition.FileName.TrimStart('"').TrimEnd('"').Trim();
            var extension = Path.GetExtension(fileName);
            var fullPathFileName = file.LocalFileName;
            if (!Path.HasExtension(fullPathFileName))
            {
                fullPathFileName = string.Concat(fullPathFileName, extension);
            }
            fileList.Add(fullPathFileName);
        }
        // Returns full file paths seperated by |
        return Request.CreateResponse(HttpStatusCode.OK, string.Join("|", fileList.ToArray()));
    Nice, thanks for sharing!
Just trying this but where can I get angular-file-upload.js and which version are you using of that?
Ok found it, seems it is using v3.x of https://github.com/danialfarid/ng-file-upload
Lee,
Thanks for the code. I'll look into integrating that in!
Tim,
Thanks for the heads up. I should update the code and comments accordingly.
Whenever I post to the api, with above code, the file gets saved with filename like
BodyPart_3b060116-....... and with no extension (like .jpg )on the server. (tried both @cssquirrel and @YodasMyDad snippet)
and the path returned to the client is the server path like d:/www/fileuploads/bodypart-3b.......
instead of just the (relative) filename
Is this the normal behaviour for the web api upload filename?
Also when I try the angular code I'm not sure if its using the correct file:
https://github.com/danialfarid/ng-file-upload/blob/master/demo/src/main/webapp/js/ng-file-upload.js
is this the correct one?
Struggling to integrate this into an Umbraco 7 project. Have a custom section and tree, have added a "file upload" menu option but I get the error message
Argument 'fileUploadController' is not a function, got undefined at Error (native)...
What might the issue be? Is there an example / demo project anywhere, which shows how to install this?
This is fantastic. Thanks for sharing. Only problem I have had is that is saves the file without an extension.