利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层
大容量文件上传早已不是什么新鲜问题,在.net 2.0时代,html5也还没有问世,要实现这样的功能,要么是改web.config,要么是用flash,要么是用一些第三方控件,然而这些解决问题的方法要么很麻烦,比如改配置,要么不稳定,比如文件上g以后,上传要么死掉,要么卡住,通过设置web.config并不能很好的解决这些问题。
这是一个html5统治浏览器的时代,在这个新的时代,这种问题已被简化并解决,我们可以利用html5分片上传的技术,那么plupload则是一个对此技术进行封装的前端脚本库,这个库的好处是可以自动检测浏览器是否支持html5技术,不支持再检测是否支持flash技术,甚至是sliverlight技术,如果支持,就使用检测到的技术。
那么这个库到哪里下载,怎么搭建呢,比较懒的童鞋还是用install-package plupload搞定吧,一个命令搞定所有事
下面给出一个例子,使用自已定义的控件来使用plupload (plupload也有自己的界面可以用),如下
plupload支持的功能这里就不细说了,什么批量上传,这里我没有用到,主要是感觉它支持的事件非常丰富,文件选取后的事件,文件上传中的事件(可获得文件的上传进度),文件上传成功的事件,文件上传失败的事件,等等
我的例子主要是上传一个单个文件,并显示上传的进度条(使用jquery的一个进度条插件)
下面的例子主要是为文件上传交给 uploadcoursepackage.ashx 来处理
/******************************************************progressbar********************************************************/ var progressbar = $("#loading").progressbar({ width: '500px', color: '#b3240e', border: '1px solid #000000' }); /******************************************************plupload***********************************************************/ //实例化一个plupload上传对象 var uploader = new plupload.uploader({ browse_button: 'browse', //触发文件选择对话框的按钮,为那个元素id runtimes: 'html5,flash,silverlight,html4',//兼容的上传方式 url: "handlers/uploadcoursepackage.ashx", //后端交互处理地址 max_retries: 3, //允许重试次数 chunk_size: '10mb', //分块大小 rename: true, //重命名 dragdrop: false, //允许拖拽文件进行上传 unique_names: true, //文件名称唯一性 filters: { //过滤器 max_file_size: '999999999mb', //文件最大尺寸 mime_types: [ //允许上传的文件类型 { title: "zip", extensions: "zip" }, { title: "pe", extensions: "pe" } ] }, //自定义参数 (键值对形式) 此处可以定义参数 multipart_params: { type: "misoft" }, // flash的配置 flash_swf_url: "../scripts/plupload/moxie.swf", // silverligh的配置 silverlight_xap_url: "../scripts/plupload/moxie.xap", multi_selection: false //true:ctrl多文件上传, false 单文件上传 }); //在实例对象上调用init()方法进行初始化 uploader.init(); uploader.bind('filesadded', function (uploader, files) { $("#<%=filesource.clientid %>").val(files[0].name); $.ajax( { type: 'post', url: 'harddiskspace.aspx/getharddiskfreespace', data: {}, datatype: 'json', contenttype: 'application/json;charset=utf-8', success: function (result) { //选择文件以后检测服务器剩余磁盘空间是否够用 if (files.length > 0) { if (parseint(files[0].size) > parseint(result.d)) { $('#error-msg').text("文件容量大于剩余磁盘空间,请联系管理员!"); } else { $('#error-msg').text(""); } } }, error: function(xhr, err, obj) { $('#error-msg').text("检测服务器剩余磁盘空间失败"); } }); }); uploader.bind('uploadprogress', function (uploader, file) { var percent = file.percent; progressbar.progress(percent); }); uploader.bind('fileuploaded', function (up, file, callback) { var data = $.parsejson(callback.response); if (data.statuscode === "1") { $("#<%=hfpackagepath.clientid %>").val(data.filepath); var id = $("#<%=hfcourseid.clientid %>").val(); __dopostback("save", id); } else { hideloading(); $('#error-msg').text(data.message); } }); uploader.bind('error', function (up, err) { alert("文件上传失败,错误信息: " + err.message); });
后台 uploadcoursepackage.ashx 的代码也重要,主要是文件分片跟不分片的处理方式不一样
using system; using system.collections.generic; using system.linq; using system.web; using system.io; namespace webui.handlers { /// <summary> /// uploadcoursepackage 的摘要说明 /// </summary> public class uploadcoursepackage : ihttphandler { public void processrequest(httpcontext context) { context.response.contenttype = "text/plain"; int statuscode = 1; string message = string.empty; string filepath = string.empty; if (context.request.files.count > 0) { try { string resourcedirectoryname = system.configuration.configurationmanager.appsettings["resourcedirectory"]; string path = context.server.mappath("~/" + resourcedirectoryname); if (!directory.exists(path)) directory.createdirectory(path); int chunk = context.request.params["chunk"] != null ? int.parse(context.request.params["chunk"]) : 0; //获取当前的块id,如果不是分块上传的。chunk则为0 string filename = context.request.params["name"]; //这里写的比较潦草。判断文件名是否为空。 string type = context.request.params["type"]; //在前面js中不是定义了自定义参数multipart_params的值么。其中有个值是type:"misoft",此处就可以获取到这个值了。获取到的type="misoft"; string ext = path.getextension(filename); //filename = string.format("{0}{1}", guid.newguid().tostring(), ext); filepath = resourcedirectoryname + "/" + filename; filename = path.combine(path, filename); //对文件流进行存储 需要注意的是 files目录必须存在(此处可以做个判断) 根据上面的chunk来判断是块上传还是普通上传 上传方式不一样 ,导致的保存方式也会不一样 filestream fs = new filestream(filename, chunk == 0 ? filemode.openorcreate : filemode.append); //write our input stream to a buffer byte[] buffer = null; if (context.request.contenttype == "application/octet-stream" && context.request.contentlength > 0) { buffer = new byte[context.request.inputstream.length]; context.request.inputstream.read(buffer, 0, buffer.length); } else if (context.request.contenttype.contains("multipart/form-data") && context.request.files.count > 0 && context.request.files[0].contentlength > 0) { buffer = new byte[context.request.files[0].inputstream.length]; context.request.files[0].inputstream.read(buffer, 0, buffer.length); } //write the buffer to a file. if (buffer != null) fs.write(buffer, 0, buffer.length); fs.close(); statuscode = 1; message = "上传成功"; } catch (exception ex) { statuscode = -1001; message = "保存时发生错误,请确保文件有效且格式正确"; util.loghelper logger = new util.loghelper(); string path = context.server.mappath("~/logs"); logger.writelog(ex.message, path); } } else { statuscode = -404; message = "上传失败,未接收到资源文件"; } string msg = "{\"statuscode\":\"" + statuscode + "\",\"message\":\"" + message + "\",\"filepath\":\"" + filepath + "\"}"; context.response.write(msg); } public bool isreusable { get { return false; } } } }
再附送一个检测服务器端硬盘剩余空间的功能吧
using system; using system.collections.generic; using system.io; using system.linq; using system.web; using system.web.script.services; using system.web.services; using system.web.ui; using system.web.ui.webcontrols; namespace webui { public partial class checkharddiskfreespace : system.web.ui.page { protected void page_load(object sender, eventargs e) { } /// <summary> /// 获取磁盘剩余容量 /// </summary> /// <returns></returns> [webmethod] public static string getharddiskfreespace() { const string strharddiskname = @"f:\"; var freespace = string.empty; var drives = driveinfo.getdrives(); var mydrive = (from drive in drives where drive.name == strharddiskname select drive).firstordefault(); if (mydrive != null) { freespace = mydrive.totalfreespace+""; } return freespace; } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: photoshop简单制作箭头方法介绍
下一篇: vue父子组件的数据传递示例