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

使用了开源的前台上传插件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. indexOf()字符位置

    package seday01; /** * int indexOf(String str) * 查找给定字符串在当前字符串中的位置,若返回值为-1,则 * 表示当前字符串中不含有给定的内容. * @ ...

  2. git fetch & pull详解

    1.简单概括 先用一张图来理一下git fetch和git pull的概念: 可以简单的概括为: git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中. 而g ...

  3. CAD总记不住?设计达人给你支招,最强口诀40条玩转设计

    绘图界有这样一个准则:绘图越快,玩的越6 相反的,CAD玩的很6 ,你的绘图效率一定不会差到哪里去,虽然不能说的太绝对,但你就操作如果玩转,一定你就操作能给你的绘图带来很多效率的提升. 当然后面就你就 ...

  4. C++ 手把手教你实现可变长的数组

    01 实现自定义的可变长数组类型 假设我们要实现一个会自动扩展的数组,要实现什么函数呢?先从下面的main函数给出的实现,看看有什么函数是需要我们实现的. int main() { MyArray a ...

  5. CSS符合选择器

    CSS复合选择器 后代选择器 后代选择器又称为包含选择器,可以选择父元素里面的子元素.其写法就是把外层标签写在前面,内层标签写在后面,中间用空格分隔,当标签发生嵌套时,内层标签就成为外层标签的后代 元 ...

  6. emacs 窗口控制

    1,调整窗口大小 c-c ^ 窗口变高 c-c } 窗口变宽 c-c { 窗口变窄 2,窗口间移动 ;;这一条语句的作用是让 windmove 在边缘的窗口也能正常运作.举个例子,当前窗口已\\ 经是 ...

  7. Shell命令-用户用户组管理之userdel、groupadd

    文件及内容处理 - userdel.groupadd 1. userdel:删除用户 userdel命令的功能说明 userdel 命令用于删除用户帐号.userdel 可删除用户帐号与相关的文件.若 ...

  8. MASK-RCNN(1)

    MASK-RCNN是一个多用途的网络,可以用来做目标检测,实例分割或者人体姿态识别.主要结构如下. 简单的说,就是首先用Faster-RCNN获得ROI,再进行ROI Align,然后输出ROI的分类 ...

  9. JAVA SE学习路径

  10. 线性回归——lasso回归和岭回归(ridge regression)

    目录 线性回归--最小二乘 Lasso回归和岭回归 为什么 lasso 更容易使部分权重变为 0 而 ridge 不行? References 线性回归很简单,用线性函数拟合数据,用 mean squ ...