MVC文件的分段上传

开发工具与关键技术:MVC、jQuery
作者:张俊辉
撰写时间:2019年03月01日
我为何要做分段上传这个功能呢?说白了就是搞事情!我们都知道,MVC不允许上传过大的文件,虽然可以通过修改配置文件提高上传大小,别人我不知道,而我或许是修改不当,偶尔能上传成功,但都以失败居多,所以上网找了很多资料,有许多其他框架上传的按例,却没发现有MVC的,但我从中学会了一些原理,因此写了这些代码,代码不是很成熟,希望对你们有帮助!
首先搭建好前端页面,在这里我就不做复杂的用了最简单最原始的文件类型的input标签,并且引用了jQuery插件,代码与效果图如下:

<div> 
        选择文件:<input type="file" id="file1" multiple accept="*" /><br />
</div>
<script src="~/Content/jquery-2.1.4.min.js"></script>

在这里插入图片描述
搭建好页面后开始书写javaScript代码,下方则是书写好的代码与注释:

//当上传文件input标签发生改变时触发事件
        $("#file1").change(function () {
            //每次上传的大小(下列相当于2M)
            var cutSize = 2 * 1024 * 1024;
            //获取文件
            var file = $("#file1").prop('files')[0];
            //当文件大小小于每次上传大小时
            if (file.size < cutSize) {
                //输出文件大小
                console.log(file.size);
            } else {
                //否则向上去整数(意思就是分为多少段)
                var fileLength = file.size / cutSize | 1;
                //循环依次上传
                for (var i = 0; i < fileLength ; i++) {
                    //声明一个对象以储存需要提交的字段与文件
                    var formData = new FormData();
                    //向formData添加一个字段count(总段数)
                    formData.append("count", fileLength)
                    //给每段文件重命名,后缀为(.part'i'i为数字)每段字段名字后缀都不一样,以i区分
                    formData.append("name", file.name + ".part" + i)
                    //下面开始截断文件,由于最后一次截断有少于2M的可能,所以当最后一次截断的位置大于文件总长度时,截断位置便等于文件总长度
                    if (cutSize * (i + 1) > file.size) {
                        //文件的最后一次截断
                        formData.append("file", file.slice(cutSize * i, file.size))
                    } else {
                        //由于i从0开始循环,因此文件也从0开始每节4M的长度截断,直至倒数第二节
                        formData.append("file", file.slice(cutSize * i, cutSize * (i + 1))) 
                    }
                    //使用ajax异步提交方式提交字段与文件
                    ajaxFile(formData, fileLength);
                };
            }
        });
        var ss = 0;//记录当前提交到第几段
        function ajaxFile(formData, count) {
            $.ajax({
                type: "post",
                url: "/HuoQuShiJian/PostbigFile1",
                data: formData,
                processData: false,
                contentType: false,
                success: function (data) {
                    //每提交成功一次ss则加多1
                    ss = ss + data;
                    //输出进度百分比,当前提交段数/总段数*100
                    console.log((ss / count) * 100  + '%');
                }
            });
        }

最后便是后台C#代码与注释了:

public ActionResult PostbigFile1()
        {
            //获取该段文件的文件名
            var name = Request.Form["name"];
            //获取当前文件的文件流
            var file = Request.Files["file"];
            //获取上传文件的 总段数
            var count = Request.Form["count"];
            //截断文件自定义的后缀名,获取原文件名
            string newFileName = name.Substring(0, name.LastIndexOf('.'));
            //判断指定目录是否存在临时存储文件夹,没有就创建(文件夹名以原文件名命名)
            if (!System.IO.Directory.Exists(Server.MapPath("~/Document/Title/Temp/" + newFileName)))
            {
                //不存在就创建目录 
                System.IO.Directory.CreateDirectory(Server.MapPath("~/Document/Title/Temp/" + newFileName));
            }
            //创建合并后的文件储存路径
            if (!System.IO.Directory.Exists(Server.MapPath("~/Document/Title/File/")))
            {
                //不存在就创建目录 
                System.IO.Directory.CreateDirectory(Server.MapPath("~/Document/Title/File/"));
            }
            //存储文件(临时文件夹)
            file.SaveAs(Server.MapPath("~/Document/Title/Temp/" + newFileName + "\\" + name));
            //获取临时存储目录下的所有切割文件
            string[] allFile = Directory.GetFiles(Server.MapPath("~/Document/Title/Temp/" + newFileName));
            //当获取文件的总条数等于上传文件的总条数时合并文件
            if(allFile.Length== int.Parse(count))
            {
                //将文件进行排序拼接
                allFile = allFile.OrderBy(s => int.Parse(Regex.Match(s, @"\d+$").Value)).ToArray();
                //判断组合的文件是否存在(临时文件夹)
                if (System.IO.File.Exists(Server.MapPath("~/Document/Title/File/" + newFileName)))//如果文件存在
                {
                    System.IO.File.Delete(Server.MapPath("~/Document/Title/File/" + newFileName));//先删除,否则新文件就不能创建
                }
                //创建空的文件流(创建二进制写入)
                FileStream FileOut = new FileStream(Server.MapPath("~/Document/Title/File/" + newFileName), FileMode.Create, FileAccess.Write);
                BinaryWriter bw = new BinaryWriter(FileOut);
                //将截断上传后的文件循环写入文件流
                for (int i = 0; i < allFile.Length; i++)
                {
                    //输入流
                    FileStream FileIn = new FileStream(allFile[i], FileMode.Open);
                    BinaryReader br = new BinaryReader(FileIn);
                    //二进制写入参数
                    byte[] data = new byte[4194304];   //流读取,缓存空间
                    int readLen = br.Read(data, 0, data.Length);//每次实际读取的字节大小
                    //二进制写入
                    bw.Write(data, 0, readLen);
                    //关闭输入流
                    FileIn.Close();
                    br.Close();
                }
                //关闭二进制写入
                bw.Close();
                FileOut.Close();
                return Json(1, JsonRequestBehavior.AllowGet);
            }
            return Json(1, JsonRequestBehavior.AllowGet);
        }

效果图如下,上传页面展示:
在这里插入图片描述
临时文件图展示:
在这里插入图片描述
上传后的文件图展示:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值