web端大文件上传-webUploader


视频说明
最近得项目中涉及到文件上传,且是大文件上传,6G,10G等。
于是找到百度得 webUploader,研究了一下再 .NET ASP.NET MVC 下得使用。
webUploader 支持 html5和flash两种文件上传形式,但最终研究,像10G这样得大文件,使用flash也是不行得。
所以必须使用html5得形式。 且支持断点续传。
直接上代码
HTML端:
<div id="uploader" class="wu-example"> <!--用来存放文件信息--> <div id="thelist" class="uploader-list"></div> <div class="btns"> <div id="picker">选择文件</div> </div> <div id="item1"> <p class="state">信息...</p> </div> </div>
JS脚本:
<script> if (!WebUploader.Uploader.support()) { alert('Web Uploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器'); throw new Error('WebUploader does not support the browser you are using.'); } @{ var path = Request.ApplicationPath == "/" ? "" : Request.ApplicationPath;} var g_appPath = '@path'; var swfUrl = g_appPath + '/Scripts/webuploader-0.1.4/dist/Uploader.swf'; var uploadChunkUrl = "@Url.Action("UploadChunk")"; var checkChunkUrl = "@Url.Action("CheckChunk")"; var mergeChunksUrl = "@Url.Action("MergeChunks")"; var singleFileMaxSize = 4000;//单位:M var GUID = WebUploader.Base.guid();//一个GUID //监听分块上传过程中的三个时间点 WebUploader.Uploader.register({ "before-send-file": "beforeSendFile", "before-send": "beforeSend" }, { //时间点1:所有分块进行上传之前调用此函数 beforeSendFile: function (file) { var deferred = WebUploader.Deferred(); //1、计算文件的唯一标记,用于断点续传 (new WebUploader.Uploader()).md5File(file, 0, 10 * 1024 * 1024) .progress(function (percentage) { $('#item1').find("p.state").text("正在读取文件信息..."); }) .then(function (val) { GUID = val; $('#item1').find("p.state").text("成功获取文件信息..."); //获取文件信息后进入下一步 deferred.resolve(); }); return deferred.promise(); }, //时间点2:如果有分块上传,则每个分块上传之前调用此函数 beforeSend: function (block) { var deferred = WebUploader.Deferred(); $.ajax({ type: "POST", url: checkChunkUrl, async:false, data: { //文件唯一标记 fileMd5: GUID, //当前分块下标 chunk: block.chunk, //当前分块大小 chunkSize: block.end - block.start }, dataType: "json", success: function (response) { if (response.ifExist) { //分块存在,跳过 deferred.reject(); } else { //分块不存在或不完整,重新发送该分块内容 deferred.resolve(); } } }); this.owner.options.formData.guid = GUID; deferred.resolve(); return deferred.promise(); } }); var uploader = WebUploader.create({ // swf文件路径 swf: swfUrl, // 文件接收服务端。 server: uploadChunkUrl, pick: { id: '#picker', //label: '上传', //innerHTML: '上传', multiple: false }, fileNumLimit: 1, runtimeOrder: "html5", //100M fileSingleSizeLimit: 1024 * 1024 * singleFileMaxSize, auto: true, chunked: true,//开始分片上传 chunkSize: 1024 * 1024 * 2,//每一片的大小 formData: { guid: GUID //自定义参数 }, //accept: { // //限制上传文件为MP4 // extensions: 'mp4', // mimeTypes: 'video/mp4', //} }); uploader.on('fileQueued', function (file) { //uploader.upload(); $('#item1').empty(); $('#item1').html( '<div id="' + file.id + '" class="item">' + '<span class="info">' + file.name + '</span><div></div>' + '<span class="state">等待上传...</span>' + '<a class="upbtn" id="btn" onclick="stop()">[取消上传]</a>' + '</div>' ); }); // 文件上传成功 uploader.on('uploadSuccess', function (file, response) { //合并文件 $('#' + file.id).find('span.state').text('文件合并中...'); $.post(mergeChunksUrl, { guid: GUID, fileName: file.name }, function (data) { if (data.r == 1) { $('#' + file.id).find('span.state').text('已上传'); } else { alert(data.err); } }); }); // 文件上传过程中创建进度条实时显示。 uploader.on( 'uploadProgress', function( file, percentage) { $('#item1').find('span.state').text('上传中 ' + Math.round(percentage * 100) + '%'); }); uploader.on('uploadError', function (file, reason) { $('#' + file.id).find('p.state').text('上传出错' + reason); }); /** * 验证文件格式以及文件大小 */ uploader.on("error", function (type) { if (type == "Q_TYPE_DENIED") { $('#item1').html("请上传JPG、PNG、GIF、BMP格式文件"); } else if (type == "Q_EXCEED_SIZE_LIMIT") { $('#item1').html("文件大小不能超过"); } else if (type == "F_EXCEED_SIZE") { $('#item1').html("文件大小不能超过" + singleFileMaxSize + "M"); } else { $('#item1').html("上传出错!请检查后重新上传!错误代码" + type); } }); uploader.on( 'uploadComplete', function( file ) { $( '#'+file.id ).find('.progress').fadeOut(); }); function start(){ uploader.upload(); $('#btn').attr("onclick","stop()"); $('#btn').text("取消上传"); } function stop(){ uploader.stop(true); $('#btn').attr("onclick","start()"); $('#btn').text("继续上传"); } </script>
控制器部分:
public class WebUploader2Controller : Controller { // GET: WebUploader public ActionResult Index() { return View(); } public ActionResult UploadChunk() { //如果进行了分片 if (Request.Form.AllKeys.Any(m => m == "chunk")) { //取得chunk和chunks int chunk = Convert.ToInt32(Request.Form["chunk"]);//当前分片在上传分片中的顺序(从0开始) int chunks = Convert.ToInt32(Request.Form["chunks"]);//总分片数 //根据GUID创建用该GUID命名的临时文件夹 string folder = Server.MapPath("~/upload/" + Request["guid"] + "/"); string path = folder + chunk; //建立临时传输文件夹 if (!Directory.Exists(Path.GetDirectoryName(folder))) { Directory.CreateDirectory(folder); } FileStream addFile = new FileStream(path, FileMode.Append, FileAccess.Write); BinaryWriter AddWriter = new BinaryWriter(addFile); //获得上传的分片数据流 var file = Request.Files[0]; Stream stream = file.InputStream; BinaryReader TempReader = new BinaryReader(stream); //将上传的分片追加到临时文件末尾 AddWriter.Write(TempReader.ReadBytes((int)stream.Length)); //关闭BinaryReader文件阅读器 TempReader.Close(); stream.Close(); AddWriter.Close(); addFile.Close(); TempReader.Dispose(); stream.Dispose(); AddWriter.Dispose(); addFile.Dispose(); return Json(new { chunked = true, hasError = false, f_ext = Path.GetExtension(file.FileName) }); } else//没有分片直接保存 { Request.Files[0].SaveAs(Server.MapPath("~/upload/" + DateTime.Now.ToFileTime() + Path.GetExtension(Request.Files[0].FileName))); return Json(new { chunked = true, hasError = false }); } } public ActionResult MergeChunks() { try { var guid = Request["guid"];//GUID var uploadDir = Server.MapPath("~/upload");//Upload 文件夹 var dir = Path.Combine(uploadDir, guid);//临时文件夹 if (Directory.Exists(dir)) { var ext = Path.GetExtension(Request["fileName"]); var files = Directory.GetFiles(dir);//获得下面的所有文件 var name = Guid.NewGuid().ToString("N") + ext; var finalPath = Path.Combine(uploadDir, name);//最终的文件名 var fs = new FileStream(finalPath, FileMode.Create); foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))//排一下序,保证从0-N Write { var bytes = System.IO.File.ReadAllBytes(part); fs.Write(bytes, 0, bytes.Length); bytes = null; System.IO.File.Delete(part);//删除分块 } fs.Flush(); fs.Close(); Directory.Delete(dir);//删除文件夹 return Json(new { r = 1, path = "/upload/" + name }); } else { return Json(new { r = 1, path = "" }); } } catch (Exception ex) { return Json(new { r = 0, err = ex.Message }); } } //检查当前分块是否上传成功 public ActionResult CheckChunk(string fileMd5, string chunk, string chunkSize) { string folder = Server.MapPath("~/upload/" + fileMd5 + "/"); string path = folder + chunk; FileInfo checkFile = new FileInfo(folder + chunk); //检查文件是否存在,且大小是否一致 if (checkFile.Exists && checkFile.Length == int.Parse(chunkSize)) { return Json(new { ifExist = 1 }); } else { //没有上传过 return Json(new { ifExist = 0 }); } } }
此demo放在了github上,地址为:https://github.com/shenqiangbin/uploadFile
扫码分享
版权说明
作者:SQBER
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
{0}
{5}
{1}
{2}回复
{4}
*昵称:
*邮箱:
个人站点:
*想说的话: