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

146 篇文章 2 订阅
128 篇文章 0 订阅

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

后台 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;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 前端可以通过以下几种方法来解决上传文件太大的问题: 1. 限制文件大小:在前端代码中限制上传文件的大小,如果文件太大,就提示用户选择一个较小的文件。 2. 分块上传:将文件分成多个小块,分别上传,这样即使文件很大,也不会占用太多的内存。 3. 压缩文件:在前端压缩文件,使得文件体积变小,再上传。 4. 后端处理:如果前端无法处理,也可以在后端进行处理,例如将大文件分块存储。 选择具体的解决方案取决于具体的需求和约束条件。 ### 回答2: 前端可以通过以下几种方式解决上传文件太大的问题。 1. 文件大小限制:前端可以通过在文件上传控件中设置文件大小限制,限制用户上传的文件最大大小。可以使用HTML5的File API来检查文件的大小,在选择文件之前进行检查并给予用户相应的提示。 2. 断点续传:前端可以使用断点续传技术,将大文件分成多个小文件进行上传。当上传中断时,用户重新上传时只需要上传断点之后的文件部分,避免重复上传整个大文件。可以使用HTML5的File API对文件进行切割,或者使用第三方库进行切割和上传。 3. 压缩文件:前端可以在上传之前对大文件进行压缩,减小文件的大小。可以使用第三方的文件压缩库进行文件压缩,然后再进行上传。 4. 服务器分片上传:将大文件分成多个小分片,分别上传到服务器。前端可以使用HTML5的File API对文件进行切割,将切割后的小分片并发地上传到服务器。服务器端接收到多个小分片后再进行合并。 5. 服务器端限制:前端可以向服务器发送文件大小等信息,并在服务器端进行判断和限制。服务器端可以设置接收文件的最大大小,当前端上传的文件超过服务器的限制时,服务器拒绝接收并返回相应提示给前端。 总而言之,前端可以通过文件大小限制、断点续传、文件压缩、服务器分片上传和服务器端限制等方式来解决上传文件太大的问题。不同的解决方案可以根据实际情况进行选择和组合使用。 ### 回答3: 当遇到上传文件太大的问题,前端可以采取以下方法来解决: 1. 设置前端限制:可以在前端进行文件大小的限制。通过在文件上传的表单元素中添加"accept"属性,并指定文件类型,例如"accept=".png,.jpg",可以限制只接受指定类型的文件。另外,在表单元素中添加"maxlength"属性,可以限制上传文件大小,避免上传过大文件。 2. 对文件进行压缩:前端可以使用压缩算法,将文件进行压缩再上传。通过压缩文件,可以减小文件大小,提高上传速度。可以使用一些前端框架或者第三方库,如JSZip、image-compressor等来实现文件压缩功能。 3. 分片上传:将大文件分成小块进行上传。前端可以使用分片上传的方式,将文件分成多个小块,逐个进行上传。这样可以避免一次性上传大文件,减轻服务器负担,提高上传速度。一些前端框架或者第三方库,如Resumable.js、plupload等可以辅助实现分片上传功能。 4. 服务端限制:与前端限制结合使用,后端也可以对上传文件大小进行限制。在服务器端设置上传文件的大小限制,当文件超过限制大小时,可以返回错误信息,提醒用户重新选择文件或者压缩文件后再上传。 综上所述,前端可以通过设置前端限制、对文件进行压缩、分片上传以及结合后端限制来解决上传文件太大的问题。通过这些方法,可以有效地减小上传文件的大小,提高文件上传的效率和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值