项目要求通过网站上传大文件,比如视频文件,通过摸索实现了文件分片来上传,然后后台进行合并。

使用了开源的前台上传插件WebUploader(http://fex.baidu.com/webuploader/)

WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。

采用大文件分片并发上传,极大的提高了文件上传效率。

直接上代码,前台cshtml

@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<link href="~/js/webuploader/webuploader.css" rel="stylesheet" />
<link href="~/js/bootstrap.min.css" rel="stylesheet" />
<script src="~/js/jquery.min.js"></script>
<script src="~/js/webuploader/webuploader.js"></script>
<title>Upload</title>
<script>
jQuery(function () {
var $ = jQuery,
$list = $('#thelist'),
$btn = $('#ctlBtn'),
state = 'pending',
fileMd5,
flag = true,
dataState,
fm = [],
fnum,
Token,
uploader;
var FileExt = ["mpg", "mpeg", "mp4", "avi"];
Token = '@ViewBag.Token';
if (Token == '' || Token== 'undefined')
{
$("#uploader").hide();
alert("登录超时,请重新登录。");
}
//监听分块上传过程中的三个时间点
WebUploader.Uploader.register({
"before-send-file": "beforeSendFile",
"before-send": "beforeSend",
"after-send-file": "afterSendFile",
}, {
beforeSendFile: function (file) {
var startTime = new Date(file.lastModifiedDate);
fileName = file.name;
var deferred = WebUploader.Deferred();
(new WebUploader.Uploader()).md5File(file, 0, 10 * 1024 * 1024)
.progress(function (percentage) {
console.log("正在读取文件");
})
.then(function (val) {
fileMd5 = val;
fm.push(fileMd5);
deferred.resolve();
});
return deferred.promise();
},
//时间点2:如果有分块上传,则每个分块上传之前调用此函数
beforeSend: function (block) {
var deferred = WebUploader.Deferred(); //上传前ajax检测一下此文件块是否已经上传 this.owner.options.formData.fileMd5 = fileMd5;
this.owner.options.formData.chunk = block.chunk;
deferred.resolve();
return deferred.promise();
},
//时间点3:所有分块上传成功后调用此函数
afterSendFile: function (file) {
var deferred = $.Deferred();
$('#' + file.id).find('p.state').text('执行最后一步');
console.log(file);
console.log(file.guid);
$.ajax({
type: "POST",
url: "/api/v1/Check/FileMerge",
data: {
guid: file.guid,
fileMd5: fm[fnum],
fileName: file.name
},
cache: false,
async: false,
success: function (response) {
fnum++;
console.log(response);
if (response.success == true) {
dataState = response;
flag = true;
} else {
flag = false;
}
deferred.resolve();
},
error: function () {
fnum++;
dataState = undefined;
flag = false;
deferred.reject();
}
}); return deferred.promise();
}
});
uploader = WebUploader.create({
resize: false,
fileNumLimit: 10,
swf: '/js/Uploader.swf',
server: '/api/v1/Check/FileSave',
pick: '#picker',
chunked: true,
chunkSize: 10 * 1024 * 1024,
chunkRetry: 5
//, formData: {
// guid: GUID
//}
});
uploader.on('beforeFileQueued', function (file) {
var isAdd = false;
for (var i = 0; i < FileExt.length; i++) {
if (file.ext == FileExt[i]) {
file.guid = WebUploader.Base.guid();
isAdd = true;
break;
}
}
return isAdd;
});
uploader.on('uploadBeforeSend', function (object, data, headers) {
//console.log(object);
headers.Authorization =Token;
data.guid = object.file.guid;
});
// 当有文件添加进来的时候
uploader.on('fileQueued', function (file) {
$list.append('<div id="' + file.id + '" class="item">' +
'<h4 class="info">' + file.name + '</h4>' +
'<input type="hidden" id="h_' + file.id + '" value="' + file.guid + '" />' +
'<p class="state">等待上传...</p>' +
'</div>');
}); // 文件上传过程中创建进度条实时显示。
uploader.on('uploadProgress', function (file, percentage) {
var $li = $('#' + file.id),
$percent = $li.find('.progress .progress-bar');
// 避免重复创建
if (!$percent.length) {
$percent = $('<div class="progress progress-striped active">' +
'<div class="progress-bar" role="progressbar" style="width: 0%">' +
'</div>' +
'</div>').appendTo($li).find('.progress-bar');
}
$li.find('p.state').text('上传中'); $percent.css('width', percentage * 100 + '%');
}); uploader.on('uploadSuccess', function (file) {
if (dataState == undefined) {
$('#' + file.id).find('p.state').text('上传失败');
$('#' + file.id).find('button').remove();
$('#' + file.id).find('p.state').before('<button id="retry" type="button" class="btn btn-primary fright retry pbtn">重新上传</button>');
flag = false;
file.setStatus('error');
}
if (dataState.success == true) {
$('#' + file.id).find('p.state').text('已上传');
$('#' + file.id).find('button').remove(); } else {
$('#' + file.id).find('p.state').text('上传失败');
flag = false;
}
}); uploader.on('uploadError', function (file) {
$('#' + file.id).find('p.state').text('上传出错');
}); uploader.on('uploadComplete', function (file) {
$('#' + file.id).find('.progress').fadeOut();
}); uploader.on('all', function (type) {
if (type === 'startUpload') {
state = 'uploading';
} else if (type === 'stopUpload') {
state = 'paused';
} else if (type === 'uploadFinished') {
state = 'done';
}
if (state === 'done') {
$btn.text('继续上传');
} else if (state === 'uploading') {
$btn.text('暂停上传');
} else {
$btn.text('开始上传');
}
});
$btn.on('click', function () {
if (state === 'uploading') {
uploader.stop();
} else if (state == 'done') {
window.location.reload();
}
else {
uploader.upload();
}
});
});
</script>
</head>
<body>
<div id="uploader" class="wu-example">
<span style="color:red">只能上传mpg、mpeg、mp4、avi格式的视频文件</span>
<div id="thelist" class="uploader-list"></div>
<div class="btns">
<div id="picker" class="webuploader-container"><div class="webuploader-pick">选择文件</div><div style="position: absolute; top: 0px; left: 0px; width: 88px; height: 34px; overflow: hidden; bottom: auto; right: auto;"><input type="file" name="file" class="webuploader-element-invisible" multiple="multiple"><label style="opacity: 0; width: 100%; height: 100%; display: block; cursor: pointer; background: rgb(255, 255, 255);"></label></div></div>
<button id="ctlBtn" class="btn btn-default">开始上传</button>
</div>
</div>
</body>
</html>

后台代码:

#region 上传视频
public IActionResult Upload()
{
ViewBag.Token = HttpContext.Request.Headers["Authorization"];//获取认证信息,传递给前台,方便Ajax请求时提供
return View();
}
/// <summary>
/// 上传文件
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> FileSave()
{
var date = Request;
var files = Request.Form.Files;
long size = files.Sum(f => f.Length);
foreach (var formFile in files)
{
if (formFile.Length > 0)
{
string fileExt = formFile.FileName.Substring(formFile.FileName.IndexOf('.')); //文件扩展名,不含“.”
long fileSize = formFile.Length; //获得文件大小,以字节为单位
//string newFileName = Guid.NewGuid().ToString() + "." + fileExt; //随机生成新的文件名
string DirPath = Path.Combine(_uploadConfig.TmpPath, Request.Form["guid"]);
if (!Directory.Exists(DirPath))
{
Directory.CreateDirectory(DirPath);
}
var filePath = DirPath + "/" + Request.Form["chunk"] + fileExt;
using (var stream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(stream); }
}
}
return Ok(new { count = files.Count, size });
} /// <summary>
/// 合并请求
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> FileMerge()
{
bool ok = false;
string errmsg = "";
try
{
var temporary = Path.Combine(_uploadConfig.TmpPath, Request.Form["guid"]);//临时文件夹
string fileName = Request.Form["fileName"];//文件名
string fileExt = Path.GetExtension(fileName);//获取文件后缀
var files = Directory.GetFiles(temporary);//获得下面的所有文件 var finalFilePath = Path.Combine(_uploadConfig.UpLoadPath + fileName);//最终的文件名
//var fs = new FileStream(finalFilePath, FileMode.Create);
using (var fs = new FileStream(finalFilePath, FileMode.Create))
{
foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))
{
var bytes = System.IO.File.ReadAllBytes(part);
await fs.WriteAsync(bytes, 0, bytes.Length);
bytes = null;
System.IO.File.Delete(part);//删除分块
}
Directory.Delete(temporary);//删除文件夹
ok = true;
}
}
catch (Exception ex)
{
ok = false;
errmsg = ex.Message;
log4net.Error(errmsg);
}
if (ok)
{
return Ok(new { success = true, msg = "" });
}
else
{
return Ok(new { success = false, msg = errmsg }); ;
}
} #endregion

 

.NetCore+WebUploader实现大文件分片上传的更多相关文章

  1. thinkphp+webuploader实现大文件分片上传

    大文件分片上传,简单来说就是把大文件切分为小文件,然后再一个一个的上传,到最后由这些小文件再合并成原来的文件 webuploader下载地址及其文档:http://fex.baidu.com/webu ...

  2. 在React中使用WebUploader实现大文件分片上传的踩坑日记!

    前段时间公司项目有个大文件分片上传的需求,项目是用React写的,大文件分片上传这个功能使用了WebUploader这个组件. 具体交互是: 1. 点击上传文件button后出现弹窗,弹窗内有选择文件 ...

  3. 30分钟玩转Net MVC 基于WebUploader的大文件分片上传、断网续传、秒传(文末附带demo下载)

    现在的项目开发基本上都用到了上传文件功能,或图片,或文档,或视频.我们常用的常规上传已经能够满足当前要求了, 然而有时会出现如下问题: 文件过大(比如1G以上),超出服务端的请求大小限制: 请求时间过 ...

  4. ASP.NET CORE使用WebUploader对大文件分片上传,并通过ASP.NET CORE SignalR实时反馈后台处理进度给前端展示

    本次,我们来实现一个单个大文件上传,并且把后台对上传文件的处理进度通过ASP.NET CORE SignalR反馈给前端展示,比如上传一个大的zip压缩包文件,后台进行解压缩,并且对压缩包中的文件进行 ...

  5. 使用webuploader实现大文件分片上传

    文件夹数据库处理逻辑 public class DbFolder { JSONObject root; public DbFolder() { this.root = new JSONObject() ...

  6. Webuploader 大文件分片上传

    百度Webuploader 大文件分片上传(.net接收)   前阵子要做个大文件上传的功能,找来找去发现Webuploader还不错,关于她的介绍我就不再赘述. 动手前,在园子里找到了一篇不错的分片 ...

  7. java springboot 大文件分片上传处理

    参考自:https://blog.csdn.net/u014150463/article/details/74044467 这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时 ...

  8. vue+大文件分片上传

    最近公司在使用vue做工程项目,实现大文件分片上传. 网上找了一天,发现网上很多代码都存在很多问题,最后终于找到了一个符合要求的项目. 工程如下: 对项目的大文件上传功能做出分析,怎么实现大文件分片上 ...

  9. iOS大文件分片上传和断点续传

    总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件 ...

随机推荐

  1. 关于.Net Core 部署在Linux下连接SqlServer数据库超时解决办法

    .Net Core 在 Linux 下连接 SqlServer 需要 SqlServer2008 SP3或以上版本,或SqlServer2012,或SqlServer2014. 如果SqlServer ...

  2. Spring MVC接口实例

    概述 前文记录了MVC模式和Spring MVC的初步认识,现在记录创建一个项目,配置Spring MVC,编写接口程序. 创建项目 打开IntelliJ IDEA,点击"File-> ...

  3. Add a Class from the Business Class Library 从业务类库添加类 (XPO)

    In this lesson, you will learn how to use business classes from the Business Class Library as is. Fo ...

  4. SpringBoot(七) SpringBoot整合Log4j

    第一种打印debug日志方式: logging.level.com.demo.mapper: debug 第二种打印debug日志方式: 在resource文件夹下新建:logback.xml < ...

  5. Unity Pixel 人物设计(1)

    草稿: 目前进度:

  6. spark streaming整合kafka

    版本说明:spark:2.2.0: kafka:0.10.0.0 object StreamingDemo { def main(args: Array[String]): Unit = { Logg ...

  7. 新MySQL查询和删除重复记录

    在工作中,我们经常会发现表中会存在重复数据,那么如何找出和删除这些数据呢? 下面,以一个小例子来说明: 1.创建学生表 1 CREATE TABLE student( 2 id INT PRIMARY ...

  8. Shell命令-用户用户组管理之id、su

    文件及内容处理 - id.su 1. id:查看用户的uid,gid及归属的用户组 id命令的功能说明 id 命令用于显示用户的 ID,以及所属群组的 ID.id 会显示用户以及所属群组的实际与有效I ...

  9. Webshell篇

    常用方法简介: 一.0day拿webshell 参考工具:织梦漏洞利用小工具 二.通过注入漏洞拿Webshell 前提条件:具有足够权限,对写入木马的文件夹要有写入权限,知道网站绝对路径. 对于mss ...

  10. day45_9_4前端(2)css

    一.css的三种css导入: 1.在标签中内部定义(不推荐). 2.在head中的style总定义样式. 3.使用link链接外部的css文件. <!DOCTYPE html> <h ...