Introduction
File upload is a common feature of many applications. Sometimes we need to upload multiple files with some data.
Problem Statement
I have developedan application using AngularJS and Web API 2 and I want to upload files as well as post some data. Both data and files, I want to post in a single request. How to achieve this?
Solution
This can be done in many ways. Here I am discussing one way that I feel is the best. The following steps are required tobe performed to achieve this. In this way, I will use directive in AngularJS and Web API.
Step 1: Define AngularJS Application.
- var app = angular.module("AngularApp", []);
Step 2: Define “uploadFiles” directive
Here, I have created a simple directive for file upload that picks up the selected files and emits "selectedFiles" event which is written in Angular controller. In this event we just add files which are selected in to the files array. Later on in this article we will look this into controller code and will discuss it.
- app.directive('uploadFiles', function () {
- return {
- scope: true,
- link: function (scope, el, attrs) {
- el.bind('change', function (event) {
- var files = event.target.files;
-
- for (var i = 0; i < files.length; i++) {
-
- scope.$emit("seletedFile", { file: files[i] });
- }
- });
- }
- };
- });
Step 3: Define angular Controller
Next step is to define the angular controller. In the controller, I have defined “selectedFile” event which is emitted from the directive. In this event we just push the selected files in to array. Later on this will used to post the files. I have also defined dummy JSON data which I want to post to Web API with selected files. Save method of the controller is use angular http service to post data and files. The transformRequest is http service property and it can be a single function that returns the transformed value. Here we just are overriding the default Transformations. This will allow us to change way of data send up to the server.
- app.controller("demoController", function ($scope, $http) {
-
- $scope.files = [];
-
-
- $scope.jsonData = {
- name: "Jignesh Trivedi",
- comments: "Multiple upload files"
- };
-
- $scope.$on("seletedFile", function (event, args) {
- $scope.$apply(function () {
-
- $scope.files.push(args.file);
- });
- });
-
-
- $scope.save = function () {
- $http({
- method: 'POST',
- url: "http://localhost:51739/PostFileWithData",
- headers: { 'Content-Type': undefined },
-
- transformRequest: function (data) {
- var formData = new FormData();
- formData.append("model", angular.toJson(data.model));
- for (var i = 0; i < data.files.length; i++) {
- formData.append("file" + i, data.files[i]);
- }
- return formData;
- },
- data: { model: $scope.jsonData, files: $scope.files }
- }).
- success(function (data, status, headers, config) {
- alert("success!");
- }).
- error(function (data, status, headers, config) {
- alert("failed!");
- });
- };
- });
Step 4: HTML Markup
Next step is to define the markup.
- <!DOCTYPE html>
- <html data-ng-app="AngularApp">
- <head>
- <meta content="IE=edge, chrome=1" http-equiv="X-UA-Compatible" />
- <title>AngularJS - Example</title>
- <script src="Script\angular.js"></script>
- <script src="Script\app.js"></script>
- <script src="Script\demoController.js"></script>
- <script src="Script\fileUploadDirective.js"></script>
-
- </head>
- <body>
- <div ng-controller="demoController">
- <b>Post JSON data and files in Same Request with AngularJS and Web API example</b>
- <br />
- <br />
- <input type="file" upload-files multiple />
- <ul>
- <li ng-repeat="file in files">{{file.name}}</li>
- </ul>
- <br />
- <br />
- <button ng-click="save()">Save</button>
- </div>
- </body>
- </html>
Step 5: Web API Controller
In this step, I have created Web API controller with standard way. In following highlight code, we get the our posted JSON data as well as posted iles.
- public class MyDataController : ApiController
- {
- [HttpPost]
- [Route("PostFileWithData")]
- public async Task<HttpResponseMessage> Post()
- {
- if (!Request.Content.IsMimeMultipartContent())
- {
- throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
- }
-
- var root = HttpContext.Current.Server.MapPath("~/App_Data/Uploadfiles");
- Directory.CreateDirectory(root);
- var provider = new MultipartFormDataStreamProvider(root);
- var result = await Request.Content.ReadAsMultipartAsync(provider);
-
-
- var model = result.FormData["jsonData"];
- if (model == null)
- {
- throw new HttpResponseException(HttpStatusCode.BadRequest);
- }
-
-
-
- foreach (var file in result.FileData)
- {
-
- }
-
- return Request.CreateResponse(HttpStatusCode.OK, "success!");
- }
- }
Output flow
Summary The way defined in this article is useful in upload the file along with the data. Hope this will help you.
Read more articles on AngularJS: