.net mvc 上传文件实时进度显示
上传文件实时进度显示
实现思路:
前端通过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));
}
```* [ ]