利用HTML5分片上传超大文件
admin
2023-01-30 10:47:56
0

在网页中直接上传大文件一直是个比较头疼的问题,主要面临的问题一般包括两类:一是上传时间长中途一旦出错会导致前功尽弃;二是服务端配置复杂,要考虑接收超大表单和超时问题,如果是托管主机没准还改不了配置,默认只能接收小于4MB的附件。


比较理想的方案是能够把大文件分片,一片一片的传到服务端,再由服务端合并。这么做的好处在于一旦上传失败只是损失一个分片而已,不用整个文件重传,而且每个分片的大小可以控制在4MB以内,服务端不用做任何设置就可适应。


常用的解决方案是RIA,以flex为例,通常是利用FileReference.load方法加载文件得到ByteArray,然后分片构造表单(flash的高版本不允许直接访问文件)。不过这个load方法只能加载较小的文件,大约不超过300MB,因此适用性不是很强。


好在现在有了HTML5,我们可以直接构造分片了,这是一个非常喜人的进步,只可惜目前适用面不广(IE啊IE,真是恨你恨得牙痒痒)。


言归正传,来看一个DEMO吧,基于ASP.Net MVC3,只是示例,很多问题做了简化处理。


主要是客户端,新特性都体现在这里:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>



    
    HTML5大文件分片上传示例
    
    


    
    上传
    等待


这里的slice方法和FormData都是html5之前不存在的。通过这样的方法,我们的表单构造出来是这样的,抓包看看:

利用HTML5分片上传超大文件

可以看到构造出来的Content-Type是multipart/form-data,也就是符合RFC标准的那个最传统的文件上传表单。另外我们同时传输的name、total等属性也都在表单里。


然后是服务端,没什么新鲜的,完全是在接收一个普通的文件:

[HttpPost]
public ActionResult Upload()
{
    //从Request中取参数,注意上传的文件在Requst.Files中
    string name = Request["name"];
    int total = Convert.ToInt32(Request["total"]);
    int index = Convert.ToInt32(Request["index"]);
    var data = Request.Files["data"];
    
    //保存一个分片到磁盘上
    string dir = Server.MapPath("~/Upload");
    string file = Path.Combine(dir, name + "_" + index);
    data.SaveAs(file);
    
    //如果已经是最后一个分片,组合
    //当然你也可以用其它方法比如接收每个分片时直接写到最终文件的相应位置上,但要控制好并发防止文件锁冲突
    if(index == total)
    {
        file = Path.Combine(dir, name);
        var fs = new FileStream(file, FileMode.Create);
        for(int i = 1;i <= total;++i)
        {
            string part = Path.Combine(dir, name + "_" + i);
            var bytes = System.IO.File.ReadAllBytes(part);
            fs.Write(bytes, 0, bytes.Length);
            bytes = null;
            System.IO.File.Delete(part);
        }
        fs.Close();
    }
    
    //返回是否成功,此处做了简化处理
    return Json(new { Error = 0 });
}


上面的DEMO很多问题是简化处理的,比如没做什么异常处理,客户端也没有判断服务端是否出错重试一类的,各位可以自己完善。


在上面的基础上,我们可以做很多功能上的扩展,比如我们可以控制所有分片是顺序上传还是并发上传,以适用不同应用。再比如我们可以在整体文件上传前以及分片上传前都先计算一下相应的HASH,发个请求询问服务器文件是否已存在,如果存在就不要重复上传了,这样就实现了“极速上传”以及“断点续传”。



相关内容

热门资讯

MEMS微纳加工进入共享时代:... 一、行业背景:科研与中试的"产线困境" 一、行业背景:科研与中试的"产线困境" 在半导体与微纳制造领...
行业首款水冷+185Hz超高刷... 一、前言:9英寸机身里塞下了整个Steam库 拿到红魔游戏平板5 Pro之前,我对它没太大期待,正常...
雷军亲自下场讲物理!小米澎程不... 7月22日,小米CEO雷军在微博抛出“灵魂三问”,9系全尺寸大空间四驱SUV你选哪个? 1. 大电池...
最新民调:特朗普的支持者对伊朗... 美伊谅解备忘录失效,停火局面被打破,双方最近大打出手。据美媒报道,美国最新民调显示,特朗普的支持者对...
专业可靠的AirTag平替销售... 智能防丢市场新选择:AirTag平替产品的核心选购逻辑与可靠源头厂商解析 在苹果AirTag带动下...
黄仁勋谈中国AI模型:非常优秀... 英伟达首席执行官黄仁勋7月21日表示,中国开源AI模型“非常优秀”,美国企业“应该使用”。他同时警告...
西门子无霜冰箱冷藏室不制冷冷冻... 1、可能是制冷剂发生了泄漏的情况;2、可能是因为风机的问题导致了不制冷情况。3、可能是外界温度的影响...
防盗门钥匙能锁门不能开门怎么回... 1、如果是喇叭锁时,导致门锁忽然打不开很可能是其锁斜舌脱勾而出现故障,这时可以将锁具螺丝下开,对锁舌...
西门子洗衣机不排水怎么回事 1、排水管不通畅或排水泵堵转。2、可能是电脑板坏了。3、排水泵与电脑板之间接触不良或排水泵损坏引起的...
西门子洗衣机不排水是什么原因 西门子洗衣机不排水可能有以下原因:1. 排水泵故障:排水泵可能损坏或堵塞,导致无法正常排水。2. 排...