加载中...

AngularJS之WebAPi上传(十)


前言

前面一系列我们纯粹是讲AngularJS,在讲一门知识时我们应该结合之前所学综合起来来做一个小的例子,前面我们讲了在MVC中上传文件的例子,在本节我们讲讲如何利用AngularJS在WebAPi中如何上传,来巩固下WebAPi并结合AngularJS中对应的一些组件学习下。

AngularJS Upload Files for WebAPi

(一)在WebAPi中我们如何获得上传本地文件的物理路径呢?需要实现此类: MultipartFormDataStreamProvider ,从该类中获取上传文件的物理路径并返回。如下:

  1. public class UploadMultipartFormProvider : MultipartFormDataStreamProvider
  2. {
  3. public UploadMultipartFormProvider(string rootPath) : base(rootPath) { }
  4. public override string GetLocalFileName(HttpContentHeaders headers)
  5. {
  6. if (headers != null &&
  7. headers.ContentDisposition != null)
  8. {
  9. return headers
  10. .ContentDisposition
  11. .FileName.TrimEnd('"').TrimStart('"');
  12. }
  13. return base.GetLocalFileName(headers);
  14. }
  15. }

(二)为避免有些浏览器不支持多个文件上传我们通过实现 ActionFilterAttribute 特性来加以判断,如下:

  1. public class MimeMultipart : ActionFilterAttribute
  2. {
  3. public override void OnActionExecuting(HttpActionContext actionContext)
  4. {
  5. if (!actionContext.Request.Content.IsMimeMultipartContent())
  6. {
  7. throw new HttpResponseException(
  8. new HttpResponseMessage(
  9. HttpStatusCode.UnsupportedMediaType)
  10. );
  11. }
  12. }
  13. public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
  14. {
  15. }
  16. }

以上两个类为我们在WebAPi中上传提供一个保障。接下来我们需要的是如何利用AngularJS来上传。

在AngularJS中上传需要用到 ng-file-upload 组件,而非 angularFileUpload 组件,在此之前一直是利用angularFileUpload组件,但是后来逐步迁移并且命名为ng-file-upload组件。同时为了一些加载效果如在github中顶部有加载线的过程,决定也在这里实现一下看看【说明:上传过程用到angular-loading-bar(加载)和ng-file-upload(上传)组件】。

脚本

(1)为了重用,我们将加载组件进行封装。

  1. //common.load.js
    (function () {
  2. 'use strict';
  3. angular
  4. .module('common.load', [
  5. 'angular-loading-bar',
  6. 'ngAnimate'
  7. ]);
  8. })();

(2)启动加载线。

  1. //loadBarCtrl.js
    (function (app) {
  2. "use strict";
  3. app.controller("loadCtrl", loadCtrl);
  4. function loadCtrl(cfpLoadingBar) {
  5. cfpLoadingBar.start();
  6. }
  7. })(angular.module("common.load"));

(3)上传文件代码

  1. //fileUploadCtrl.js
    (function (app) {
  2. 'use strict';
  3. app.controller('fileUploadCtrl', fileUploadCtrl);
  4. fileUploadCtrl.$inject = ['$scope', '$http', '$timeout', 'Upload'];
  5. function fileUploadCtrl($scope, $http, $timeout, Upload, cfpLoadingBar) {
  6. $scope.upload = [];
  7. $scope.UploadedFiles = [];
  8. $scope.startUploading = function ($files) {
  9. for (var i = 0; i < $files.length; i++) {
  10. var $file = $files[i];
  11. (function (index) {
  12. $scope.upload[index] = Upload.upload({
  13. url: "/api/upload",
  14. method: "POST",
  15. file: $file,
  16. withCredentials: false
  17. }).progress(function (evt) {
  18. }).success(function (data, status, headers, config) {
  19. $scope.UploadedFiles.push({ FileName: data.FileName, FilePath: data.LocalFilePath, FileLength: data.FileLength });
  20. cfpLoadingBar.complete();
  21. }).error(function (data, status, headers, config) {
  22. });
  23. })(i);
  24. }
  25. }
  26. }
  27. })(angular.module("common.load"));

(4)加载主模块以及依赖模块。

  1. //app.js
    (function () {
  2. 'use strict';
  3. angular
  4. .module('angularUploadApp', [
  5. 'ngRoute',
  6. 'ngFileUpload',
  7. 'common.load'
  8. ])
  9. .config(config)
  10. config.$inject = ['$routeProvider'];
  11. function config($routeProvider) {
  12. $routeProvider
  13. .when('/', {
  14. templateUrl: '../../app/templates/fileUpload.html',
  15. controller: 'fileUploadCtrl'
  16. })
  17. .otherwise({
  18. redirectTo: '/'
  19. });
  20. }
  21. })();

界面 

  1. @{
  2. Layout = null;
  3. }
  4. <!DOCTYPE html>
  5.  
  6. <html>
  7. <head>
  8. <meta charset="utf-8" />
  9. <title></title>
  10. <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
  11. <link href="~/Content/loading-bar.min.css" rel="stylesheet" media="all" />
  12. </head>
  13. <body ng-app="angularUploadApp" ng-controller="loadCtrl">
  14. <nav class="navbar navbar-default" role="navigation">
  15.  
  16. <div class="navbar-header">
  17. <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
  18. <span class="sr-only">Toggle navigation</span>
  19. <span class="icon-bar"></span>
  20. <span class="icon-bar"></span>
  21. <span class="icon-bar"></span>
  22. </button>
  23. <a class="navbar-brand" href="http://www.cnblogs.com/createmyself">Angular File WebAPi Upload by <i style="color:#2da12d;font-weight:bolder;">xpy0928</i></a>
  24. </div>
  25. <div id="navbar" class="navbar-collapse collapse">
  26.  
  27. </div>
  28.  
  29. </nav>
  30. <div class="container">
  31. <div ng-include src="'../../app/templates/fileUpload.html'"></div>
  32. </div>
  33. <script src="../../Scripts/jquery-1.10.2.min.js"></script>
  34. <script src="../../Scripts/angular.min.js"></script>
  35. <script src="../../Scripts/angular-animate.min.js"></script>
  36. <script src="../../Scripts/angular-route.js"></script>
  37. <script src="../../app/plugins/loading-bar.min.js"></script>
  38. <script src="../../app/modules/common.load.js"></script>
  39. <script src="../../Scripts/ng-file-upload.min.js"></script>
  40. <script src="../../app/app.js"></script>
  41. <script src="../../app/controllers/loadBarCtrl.js"></script>
  42. <script src="../../app/controllers/fileUploadCtrl.js"></script>
  43. </body>
  44. </html>

模板页:

  1. <div class="row" ng-controller="fileUploadCtrl">
  2. <div class="col-xs-3">
  3. <div>
  4. <input type="file" accept="images/*" ngf-pattern="'.png,.jpg,.gif'" ngf-select="startUploading($files)" multiple>
  5. </div>
  6. </div>
  7. <div class="col-xs-9">
  8. <div class="panel-body">
  9. <div class="panel panel-default" ng-repeat="uploadedFile in UploadedFiles track by $index">
  10. <div class="panel-heading">
  11. <strong>{{uploadedFile.FileName}}</strong>
  12. </div>
  13. <div class="panel-body">
  14. <div class=" media">
  15. <a class="pull-left" href="#">
  16. <img class="media-object" width="100" ng-src="../uploadimages/{{uploadedFile.FileName}}" />
  17. </a>
  18. <div class="media-body">
  19. <div class="lead" style="font-size:14px;color: crimson;width:500px;word-wrap:break-word">{{uploadedFile.FilePath}}</div>
  20. </div>
  21. </div>
  22. </div>
  23. <div class="panel-footer">
  24. 图片总字节: <span style="color:black">{{uploadedFile.FileLength}}</span>
  25. </div>
  26. </div>
  27. </div>
  28.  
  29. </div>
  30. </div>

后台api服务:

  1. [RoutePrefix("api/upload")]
  2. public class FileUploadController : ApiController
  3. {
  4. [Route("")]
  5. [MimeMultipart]
  6. public async Task<FileUploadResult> Post()
  7. {
  8. var uploadPath = HttpRuntime.AppDomainAppPath + "UploadImages";
  9. if (!Directory.Exists(uploadPath))
  10. Directory.CreateDirectory(uploadPath);
  11. var multipartFormDataStreamProvider = new UploadMultipartFormProvider(uploadPath);
  12. await Request.Content.ReadAsMultipartAsync(multipartFormDataStreamProvider);
  13. string _localFileName = multipartFormDataStreamProvider
  14. .FileData.Select(multiPartData => multiPartData.LocalFileName).FirstOrDefault();
  15. return new FileUploadResult
  16. {
  17. LocalFilePath = _localFileName,
  18. FileName = Path.GetFileName(_localFileName),
  19. FileLength = new FileInfo(_localFileName).Length
  20. };
  21. }
  22. }

首先我们来看看例子搭建的结构:

生成界面效果:

 

下面我们来演示下最终效果:

 

总结

(1)在WebAPi中用到路由特性时,若在控制器中如  [RoutePrefix("api/upload")] 此时在方法中若未有  [Route("")] 此时在上传的url必须显示添加Post如: url: "/api/upload/post" 若添加则不用显示添加方法名。

(2)在angular中加载模板为

  1. <div ng-include src="''"></div> 【注】:src中要加单引号,否则出错
  2. 或者
  3. <div ng-include></div>

(3)对于在WebAPi中上传可以参看此链接,更加详细。

WebAPi:https://github.com/stewartm83/angular-fileupload-sample

对于AngularJS组件中的加载和上传还有更多用法,可以参看如下链接:

ng-file-upload:https://github.com/danialfarid/ng-file-upload

angular-loading-bar:https://github.com/chieffancypants/angular-loading-bar


还没有评论.