AngularJS之WebAPi上傳(十)
前言
前面一系列我們純粹是講AngularJS,在講一門知識時我們應該結合之前所學綜合起來來做一個小的例子,前面我們講了在MVC中上傳文件的例子,在本節我們講講如何利用AngularJS在WebAPi中如何上傳,來鞏固下WebAPi並結合AngularJS中對應的一些組件學習下。
AngularJS Upload Files for WebAPi
(一)在WebAPi中我們如何獲得上傳本地文件的物理路徑呢?需要實現此類: MultipartFormDataStreamProvider ,從該類中獲取上傳文件的物理路徑並返回。如下:
public class UploadMultipartFormProvider : MultipartFormDataStreamProvider
{
public UploadMultipartFormProvider(string rootPath) : base(rootPath) { }
public override string GetLocalFileName(HttpContentHeaders headers)
{
if (headers != null &&
headers.ContentDisposition != null)
{
return headers
.ContentDisposition
.FileName.TrimEnd('"').TrimStart('"');
}
return base.GetLocalFileName(headers);
}
}
(二)為避免有些瀏覽器不支持多個文件上傳我們通過實現 ActionFilterAttribute 特性來加以判斷,如下:
public class MimeMultipart : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(
new HttpResponseMessage(
HttpStatusCode.UnsupportedMediaType)
);
}
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
}
}
以上兩個類為我們在WebAPi中上傳提供一個保障。接下來我們需要的是如何利用AngularJS來上傳。
在AngularJS中上傳需要用到 ng-file-upload 組件,而非 angularFileUpload 組件,在此之前一直是利用angularFileUpload組件,但是后來逐步遷移並且命名為ng-file-upload組件。同時為了一些加載效果如在github中頂部有加載線的過程,決定也在這里實現一下看看【說明:上傳過程用到angular-loading-bar(加載)和ng-file-upload(上傳)組件】。
腳本
(1)為了重用,我們將加載組件進行封裝。
//common.load.js
(function () { 'use strict'; angular .module('common.load', [ 'angular-loading-bar', 'ngAnimate' ]); })();
(2)啟動加載線。
//loadBarCtrl.js
(function (app) { "use strict"; app.controller("loadCtrl", loadCtrl); function loadCtrl(cfpLoadingBar) { cfpLoadingBar.start(); } })(angular.module("common.load"));
(3)上傳文件代碼
//fileUploadCtrl.js
(function (app) { 'use strict'; app.controller('fileUploadCtrl', fileUploadCtrl); fileUploadCtrl.$inject = ['$scope', '$http', '$timeout', 'Upload']; function fileUploadCtrl($scope, $http, $timeout, Upload, cfpLoadingBar) { $scope.upload = []; $scope.UploadedFiles = []; $scope.startUploading = function ($files) { for (var i = 0; i < $files.length; i++) { var $file = $files[i]; (function (index) { $scope.upload[index] = Upload.upload({ url: "/api/upload", method: "POST", file: $file, withCredentials: false }).progress(function (evt) { }).success(function (data, status, headers, config) { $scope.UploadedFiles.push({ FileName: data.FileName, FilePath: data.LocalFilePath, FileLength: data.FileLength }); cfpLoadingBar.complete(); }).error(function (data, status, headers, config) { }); })(i); } } } })(angular.module("common.load"));
(4)加載主模塊以及依賴模塊。
//app.js
(function () { 'use strict'; angular .module('angularUploadApp', [ 'ngRoute', 'ngFileUpload', 'common.load' ]) .config(config) config.$inject = ['$routeProvider']; function config($routeProvider) { $routeProvider .when('/', { templateUrl: '../../app/templates/fileUpload.html', controller: 'fileUploadCtrl' }) .otherwise({ redirectTo: '/' }); } })();
界面
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/loading-bar.min.css" rel="stylesheet" media="all" />
</head>
<body ng-app="angularUploadApp" ng-controller="loadCtrl">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<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>
</div>
<div id="navbar" class="navbar-collapse collapse">
</div>
</nav>
<div class="container">
<div ng-include src="'../../app/templates/fileUpload.html'"></div>
</div>
<script src="../../Scripts/jquery-1.10.2.min.js"></script>
<script src="../../Scripts/angular.min.js"></script>
<script src="../../Scripts/angular-animate.min.js"></script>
<script src="../../Scripts/angular-route.js"></script>
<script src="../../app/plugins/loading-bar.min.js"></script>
<script src="../../app/modules/common.load.js"></script>
<script src="../../Scripts/ng-file-upload.min.js"></script>
<script src="../../app/app.js"></script>
<script src="../../app/controllers/loadBarCtrl.js"></script>
<script src="../../app/controllers/fileUploadCtrl.js"></script>
</body>
</html>
模板頁:
<div class="row" ng-controller="fileUploadCtrl">
<div class="col-xs-3">
<div>
<input type="file" accept="images/*" ngf-pattern="'.png,.jpg,.gif'" ngf-select="startUploading($files)" multiple>
</div>
</div>
<div class="col-xs-9">
<div class="panel-body">
<div class="panel panel-default" ng-repeat="uploadedFile in UploadedFiles track by $index">
<div class="panel-heading">
<strong>{{uploadedFile.FileName}}</strong>
</div>
<div class="panel-body">
<div class=" media">
<a class="pull-left" href="#">
<img class="media-object" width="100" ng-src="../uploadimages/{{uploadedFile.FileName}}" />
</a>
<div class="media-body">
<div class="lead" style="font-size:14px;color: crimson;width:500px;word-wrap:break-word">{{uploadedFile.FilePath}}</div>
</div>
</div>
</div>
<div class="panel-footer">
圖片總字節: <span style="color:black">{{uploadedFile.FileLength}}</span>
</div>
</div>
</div>
</div>
</div>
后台api服務:
[RoutePrefix("api/upload")]
public class FileUploadController : ApiController
{
[Route("")]
[MimeMultipart]
public async Task<FileUploadResult> Post()
{
var uploadPath = HttpRuntime.AppDomainAppPath + "UploadImages";
if (!Directory.Exists(uploadPath))
Directory.CreateDirectory(uploadPath);
var multipartFormDataStreamProvider = new UploadMultipartFormProvider(uploadPath);
await Request.Content.ReadAsMultipartAsync(multipartFormDataStreamProvider);
string _localFileName = multipartFormDataStreamProvider
.FileData.Select(multiPartData => multiPartData.LocalFileName).FirstOrDefault();
return new FileUploadResult
{
LocalFilePath = _localFileName,
FileName = Path.GetFileName(_localFileName),
FileLength = new FileInfo(_localFileName).Length
};
}
}
首先我們來看看例子搭建的結構:

生成界面效果:
下面我們來演示下最終效果:

總結
(1)在WebAPi中用到路由特性時,若在控制器中如 [RoutePrefix("api/upload")] 此時在方法中若未有 [Route("")] 此時在上傳的url必須顯示添加Post如: url: "/api/upload/post" 若添加則不用顯示添加方法名。
(2)在angular中加載模板為
<div ng-include src="''"></div> 【注】:src中要加單引號,否則出錯 或者 <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
非常感謝您花時間讀完這篇文章,如果您覺得此文不錯,請點一下“推薦”按鈕,您的“推薦”就是對我最大的鼓勵以及不懈努力的肯定。
本文版權歸作者和博客園所有,來源網址:http://www.cnblogs.com/CreateMyself/歡迎各位轉載,轉載文章之后必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責任的權利以及小小的鄙視。

