利用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 来处理

rush:js;"> /******************************************************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',//<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>最大尺寸
      mime_types: [ //允许<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>类型
        { title: "Zip",extensions: "zip" },{ title: "PE",extensions: "pe" }
      ]
    },//自<a href="https://www.jb51.cc/tag/dingyicanshu/" target="_blank" class="keywords">定义参数</a> (键值对形式) 此处可以<a href="https://www.jb51.cc/tag/dingyicanshu/" target="_blank" class="keywords">定义参数</a>
    multipart_p<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>ms: {
      type: "misoft"
    },// FLASH的配置
    flash_swf_url: "../Scripts/plupload/Moxie.swf",// Silverligh的配置
    silverlight_xap_url: "../Scripts/plupload/Moxie.xap",multi_selection: false //true:ctrl多<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>,false 单<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a> 
  });

  //在实例对象上<a href="https://www.jb51.cc/tag/diaoyong/" target="_blank" class="keywords">调用</a>init()<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>进行初始化
  uploader.init();

  uploader.bind('FilesAdded',function (uploader,files) {
    $("#<%=fileSource.ClientID %>").val(files[0].name);
    $.ajax(
    {
      type: 'post',url: 'Hard<a href="https://www.jb51.cc/tag/dis/" target="_blank" class="keywords">dis</a>kSpace.aspx/GetHard<a href="https://www.jb51.cc/tag/dis/" target="_blank" class="keywords">dis</a>kFreeSpace',data: {},dataType: 'json',contentType: 'application/json;charset=utf-8',success: function (result) {
        //选择<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>以后检测服务器剩余磁盘空间是否够用
        if (files.length > 0) {
          if (parseInt(files[0].size) > parseInt(result.d)) {
            $('#error-msg').text("<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>容量大于剩余磁盘空间,请联系<a href="https://www.jb51.cc/tag/guanliyuan/" target="_blank" class="keywords">管理员</a>!");
          } else {
            $('#error-msg').text("");
          }
        }
      },error: function(xhr,err,obj) {
        $('#error-msg').text("检测服务器剩余磁盘空间失败");
      }
    });
  });

  uploader.bind('UploadProgress',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',err) {
    alert("<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>失败,<a href="https://www.jb51.cc/tag/cuowu/" target="_blank" class="keywords">错误</a>信息: " + err.message);
  });

后台 UploadCoursePackage.ashx 的代码也重要,主要是文件分片跟不分片的处理方式不一样

rush:csharp;"> using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO;

namespace WebUI.Handlers
{
///


/// UploadCoursePackage 的摘要说明
///

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 = Sy<a href="https://www.jb51.cc/tag/stem/" target="_blank" class="keywords">stem</a>.Con<a href="https://www.jb51.cc/tag/fig/" target="_blank" class="keywords">fig</a>uration.Con<a href="https://www.jb51.cc/tag/fig/" target="_blank" class="keywords">fig</a>urationManager.AppSettings["resourceDirectory"];
      string path = context.Server.MapPath("~/" + resourceDirectoryName);
      if (!Directory.Exists(path))
        Directory.CreateDirectory(path);

      int chunk = context.Request.P<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>ms["chunk"] != null ? int.Parse(context.Request.P<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>ms["chunk"]) : 0; //<a href="https://www.jb51.cc/tag/huoqu/" target="_blank" class="keywords">获取</a>当前的块ID,如果不是分块<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>的。chunk则为0
      string fileName = context.Request.P<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>ms["name"]; //这里写的比较潦草。判断<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>名是否为空。
      string type = context.Request.P<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>ms["type"]; //在前面JS中不是定义了自<a href="https://www.jb51.cc/tag/dingyicanshu/" target="_blank" class="keywords">定义参数</a>multipart_p<a href="https://www.jb51.cc/tag/ara/" target="_blank" class="keywords">ara</a>ms的值么。其中有个值是type:"misoft",此处就可以<a href="https://www.jb51.cc/tag/huoqu/" target="_blank" class="keywords">获取</a>到这个值了。<a href="https://www.jb51.cc/tag/huoqu/" target="_blank" class="keywords">获取</a>到的type="misoft";

      string ext = Path.GetExtension(fileName);
      //fileName = string.Format("{0}{1}",Guid.NewGuid().ToString(),ext);
      filepath = resourceDirectoryName + "/" + fileName;
      fileName = Path.Combine(path,fileName);

      //对<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>流进行存储 需要注意的是 files目录必须存在(此处可以做个判断) 根据上面的chunk来判断是块<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>还是普通<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a> <a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>方式不一样 ,导致的保存方式也会不一样
      FileStream fs = new FileStream(fileName,chunk == 0 ? FileMode.Ope<a href="https://www.jb51.cc/tag/nor/" target="_blank" class="keywords">nor</a>Create : 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,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,buffer.Length);
      }

      //write the buffer to a file.
      if (buffer != null)
        fs.Write(buffer,buffer.Length);
      fs.Close();

      statuscode = 1;
      message = "<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>成功";

    }
    catch (Exception ex)
    {
      statuscode = -1001;
      message = "保存时发生<a href="https://www.jb51.cc/tag/cuowu/" target="_blank" class="keywords">错误</a>,请确保<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>有效且格式正确";

      Util.LogHelper logger = new Util.LogHelper();
      string path = context.Server.MapPath("~/Logs");
      logger.WriteLog(ex.Message,path);
    }
  }
  else
  {
    statuscode = -404;
    message = "<a href="https://www.jb51.cc/tag/shangchuan/" target="_blank" class="keywords">上传</a>失败,未接收到资源<a href="https://www.jb51.cc/tag/wenjian/" target="_blank" class="keywords">文件</a>";
  }

  string msg = "{\"statusCode\":\"" + statuscode + "\",\"message\":\"" + message + "\",\"filePath\":\"" + filepath + "\"}";
  context.Response.Write(msg);
}

public bool IsReusable
{
  get
  {
    return false;
  }
}

}
}

再附送一个检测服务器端硬盘剩余空间的功能

rush:csharp;"> 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>
/// <a href="https://www.jb51.cc/tag/huoqu/" target="_blank" class="keywords">获取</a>磁盘剩余容量
/// </summary>
/// <returns></returns>
[WebMethod]
public static string GetHard<a href="https://www.jb51.cc/tag/dis/" target="_blank" class="keywords">dis</a>kFreeSpace()
{
  const string strHard<a href="https://www.jb51.cc/tag/dis/" target="_blank" class="keywords">dis</a>kName = @"F:\";

  var freeSpace = string.Empty;
  var drives = DriveInfo.GetDrives();
  var myDrive = (from drive in drives
    where drive.Name == strHard<a href="https://www.jb51.cc/tag/dis/" target="_blank" class="keywords">dis</a>kName
    select drive).F<a href="https://www.jb51.cc/tag/irs/" target="_blank" class="keywords">irs</a>tOrDefault();
  if (myDrive != null)
  {
    freeSpace = myDrive.TotalFreeSpace+""; 
  }
  return freeSpace;
}

}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...