-
-
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.