上传文件实时进度显示

实现思路:
前端通过ajax,表单等方法上传文件(和普通上传方法一样),后台实时更新上传进度,前端页面与此同时通过ajax轮询请求后台上传进度然后更新页面提示信息(其实可以通过WebSoket与后台保持长连接,这里采用ajax,有兴趣的可以自己尝试一下)
代码:

前端:

   //因为公司用的angular.js 这里使用的是angular.js的Upload插件
          Upload.upload({
                 method: "POST",
                 //服务端接收 
                 url: parent.uploadObject.MeetingHost + 'UploadMeeting/Meeting',
                 //上传的同时带的参数  
                 data: {
                     'UserName': parent.uploadObject.UserName,
                     'UserId': parent.uploadObject.UserId
                 },
                 withCredentials: false,
                 file: $("#FileUpload").prop('files')
             }).progress(function (evt) {
             }).success(function (data, status, headers, config) {
                 layer.close(index);
                 $scope.processVal = 0;
                 if (data.Code == 101) {
                     $scope.progresFlag = false;
                     layer.msg(data.Message, { time: 1000 });
                     $scope.MeetingModel.FileDirectory = data.Data;
                     console.log(data);
                 }
                 else {
                     $scope.progresFlag = false;
                     layer.msg(data.Message);
                     console.log(data);
                 }
             }).error(function (data, status, headers, config) {
                 console.log(data);
                 layer.close(index);
                 //上传失败 
                 layer.alert("上传接口出现异常", { icon: 2 });
             });
             //上面代码功能就是上传文件到后台
             //上传文件的同时提交一个新的ajax请求到后台查询进度
             //获取上传进度
             $scope.getUploadProgress = function () {
                 $.ajax({
                     url: parent.uploadObject.MeetingHost + 'UploadMeeting/Progress',
                     type: 'GET',
                     dataType: 'JSONP',
                     data: { 'UserId': parent.uploadObject.UserId },
                     success: function (data) {
                         console.log(data);
                         $scope.processVal = data.schedule * 1;
                         console.log($scope.processVal);
                         if ($scope.processVal < 100) {
                         //如果进度小于100说明文件上传未结束,则继续请求
                             $timeout($scope.getUploadProgress(), 1000);
                         }
                         else {
                             $scope.processVal = 0
                         }
                     }
                 });
             }
            $scope.getUploadProgress();

后台代码:(我这里采用.net实现)

这里保存进度的机制采用.net的Cache实现

   /// <summary>
        /// 响应model
        /// </summary>
        class ResposeModel
        {
            /// <summary>
            /// 结果码
            /// </summary>
            public ResponseCode Code { get; set; }
            /// <summary>
            /// 处理提示消息
            /// </summary>
            public string Message { get; set; }
            /// <summary>
            /// 返回数据
            /// </summary>
            public object Data { get; set; }
        }
        /// <summary>
        /// 上传进度model
        /// </summary>
        class UploadProgress
        {
            public Guid UserId { set; get; }
            /// <summary>
            /// 上传文件名
            /// </summary>
            public string fileName { set; get; }
            /// <summary>
            /// 文件大小
            /// </summary>
            public int fileSize { set; get; }
            /// <summary>
            /// 上传进度
            /// </summary>
            public double schedule { set; get; }
            /// <summary>
            /// 上传已耗时
            /// </summary>
            public long costTime { set; get; }
            /// <summary>
            /// 文件已上传
            /// </summary>
            public int fileFinished { set; get; }
            /// <summary>
            /// 是否已经成功上传
            /// </summary>
            public Boolean fileisSuccess { set; get; }
        }
        /// <summary>
        /// 响应状态
        /// </summary>
        enum ResponseCode
        {
            /// <summary>
            /// 成功
            /// </summary>
            Success = 101,
            /// <summary>
            /// 失败
            /// </summary>
            Fail = 201,
            /// <summary>
            /// 文件需要转码
            /// </summary>
            FileNeedTranscoding = 202
        }
    }
 [HttpPost]
        public JsonResult Meeting(string UserName, string UserId)
        {
            ResposeModel jsonModel = new ResposeModel();//响应model实体
            jsonModel.Code = ResponseCode.Fail;
            jsonModel.Message = "上传失败";
            UploadProgress uploadProgress = new UploadProgress();
            if (UserName == null)
            {
                UserName = "default";//如果没有传入用户名则保存在默认文件夹
            }
            string filePath = ZhandianPath + MeetingPath + UserName + "/";
            if (!Directory.Exists(filePath))
                Directory.CreateDirectory(filePath);
            try
            {
                DateTime begin = DateTime.Now.ToLocalTime();//开始上传时间 
                HttpFileCollectionBase files = HttpContext.Request.Files;
                HttpPostedFileBase file = files[0];
                string suffix = "." + file.FileName.Split('.')[1];
                if (file == null || file.ContentLength <= 0)
                {
                    jsonModel.Message = "文件不能为空";
                }
                else
                {
                    string fileName = DateTime.Now.ToString("yyyyMMddHHmmss") + suffix;
                    string filePathName = filePath + fileName;
                    uploadProgress.fileName = file.FileName;//设置上传文件名
                    uploadProgress.fileSize = file.ContentLength;//设置上传文件大小(单位:字节)
                    uploadProgress.UserId = Guid.Parse(UserId);
                    //开始处理
                    byte[] byteArray = new byte[1000];
                    Stream _reader = file.InputStream;
                    int len = _reader.Read(byteArray, 0, byteArray.Length);
                    using (FileStream _fStream = new FileStream(filePathName, FileMode.Create))
                    {
                        while (len > 0)
                        {
                            _fStream.Write(byteArray, 0, len);
                            uploadProgress.costTime = (long)(DateTime.Now.ToLocalTime() - begin).TotalMilliseconds;//写入已耗时
                            uploadProgress.fileFinished += len;//文件已经上传字节
                            uploadProgress.schedule = Convert.ToDouble(uploadProgress.fileFinished * 100 / uploadProgress.fileSize);//文件上传进度(百分比)
                            HttpContext.Cache[UserId] = uploadProgress;
                            System.Threading.Thread.Sleep(10);//模拟延时操作(正式环境注释该代码)
                            len = _reader.Read(byteArray, 0, byteArray.Length);
                        }
                    }
                    _reader.Close();
                    jsonModel.Code = ResponseCode.Success;
                    jsonModel.Data = filePathName.Replace(ZhandianPath, "");
                    jsonModel.Message = "上传成功";
                }
            }
            catch (Exception ex)
            {
                jsonModel.Message = ex.Message;
            }
            return Json(jsonModel);
        }
        //我这里有跨域问题所以采用jsonp
         /// <summary>
        /// 获取上传进度(前台请求此方法获取进度)
        /// </summary>
        /// <param name="UserId">用户唯一标示</param>
        /// <param name="callback">jsonp回调</param>
        /// <returns></returns>
        public string Progress(string UserId, string callback)
        {
            UploadProgress uploadProgress = HttpContext.Cache[UserId] == null ? new UploadProgress() : HttpContext.Cache[UserId] as UploadProgress;
            if (uploadProgress.fileisSuccess)
            {
                uploadProgress = new UploadProgress();
            }
            else
            {
                if (uploadProgress.fileFinished != 0 && (uploadProgress.fileFinished == uploadProgress.fileSize))
                {
                    uploadProgress.fileisSuccess = true;//上传成功
                    HttpContext.Cache[UserId] = uploadProgress;
                }
            }
            return string.Format("{0}({1})", callback, Newtonsoft.Json.JsonConvert.SerializeObject(uploadProgress));
        }
```* [ ]