JavaScript

超轻量级php框架startmvc

利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层

更新时间:2020-04-30 04:12:01 作者:startmvc
大容量文件上传早已不是什么新鲜问题,在.net2.0时代,HTML5也还没有问世,要实现这样的功

大容量文件上传早已不是什么新鲜问题,在.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;
 }
 }
}

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

plupload 进度条 plupload 加进度条 plupload 上传进度条