asp.net 文件分片上传

简介: asp.net 文件分片上传

最近在研究文件上传,里面的门道还是挺多的,网上大多数文章比较杂乱,代码都是片段,对于新手小白来说难度较高,所以在此详细写一下今天看到的一个demo,关于文件分片上传的。


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
</head>
<body>
    <input type="file" id="file6" multiple><button type="button" class="btnFile6">分片上传</button><div class="result"></div>
</body>
</html>
<script>
    $(".btnFile6").click(function () {
        var upload = function (file, skip) {
            var formData = new FormData();//初始化一个FormData对象
            var blockSize = 1000000;//每块的大小
            var nextSize = Math.min((skip + 1) * blockSize, file.size);//读取到结束位置
            var fileData = file.slice(skip * blockSize, nextSize);//截取 部分文件 块
            formData.append("file", fileData);//将 部分文件 塞入FormData
            formData.append("fileName", file.name);//保存文件名字
            $.ajax({
                url: "Handler.ashx",
                type: "POST",
                data: formData,
                processData: false,  // 告诉jQuery不要去处理发送的数据
                contentType: false,   // 告诉jQuery不要去设置Content-Type请求头
                success: function (responseText) {
                    $(".result").html("已经上传了" + (skip + 1) + "块文件");
                    if (file.size <= nextSize) {//如果上传完成,则跳出继续上传
                        alert("上传完成");
                        return;
                    }
                    upload(file, ++skip);//递归调用
                }
            });
        };
        var file = $("#file6")[0].files[0];
        upload(file, 0);
    });
</script>


后端一般处理程序:


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
namespace WebApplication1
{
    /// <summary>
    /// Handler 的摘要说明
    /// </summary>
    public class Handler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            //保存文件到指定目录
            var filePath = @"D:\penglong\study\WebApplication1\WebApplication1\uploads\" + context.Request.Form["fileName"];
            //创建一个追加(FileMode.Append)方式的文件流
            using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write))
            {
                using (BinaryWriter bw = new BinaryWriter(fs))
                {
                    //读取文件流
                    BinaryReader br = new BinaryReader(context.Request.Files[0].InputStream);
                    //将文件留转成字节数组
                    byte[] bytes = br.ReadBytes((int)context.Request.Files[0].InputStream.Length);
                    //将字节数组追加到文件
                    bw.Write(bytes);
                }
            }
        }
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}


浏览器监听的请求过程如图:


  

  

目前代码里设置的是1M一片,2.25MB的文件被分为了3片,因此请求的时候请求了三次,这样,我们就可以上传大文件了。(webconfig可以设置最大文件为2G,当上传的文件超过2G或者我们不希望更改webconfig配置时,则可以使用这个进行分片上传,网上大多数分片插件的原理也是如此,通过构造formdata对象进行多次上传,然后在后端进行文件的合并操作)。


参考链接:https://www.cnblogs.com/fjzhang/p/7227401.html?utm_source=itdadao&utm_medium=referral



补:


从demo上讲,上面的案例基本没有问题,但是实际使用的场景中,会存在这样一个问题,由于文件是存在磁盘上的,当用户再次上传同名文件时,文件流会被继续追加到这个文件里,而不是另起一个文件,或者做覆盖操作,因为FileMode.Append模式下会检测当前路径是否存在这个文件,存在则append。


那么该如何解决这个问题呢,一开始我想到的是通过size判断,如果传入文件的size,不等于读取到的文件流对象的大小,则说明文件还没有传输完毕,则可以继续append。但是当等于时,是需要新建文件的,所以就得重命名了,windows系统再重命名的时候会在原有文件名后面带上副本啊之类的名称,我这里为了简洁,直接在前端读取了一个系统时间作为唯一标识,来混入文件名,这样后台保存的文件就不会存在文件流并入一个文件的问题了。


代码如图:


  

  


这里有一点需要注意,为什么我不在后端去生成这个时间标识,而是在前端生成呢?原因是这里是进行分片上传的,会多次请求后端接口,如果在后端生成唯一标识,那么在上传文件的方法里会生成多个文件,这样是不对的,所以这里在前端做了参数取值,每次点击的时候生成一个唯一标识,即便分N次上传,名称也是同一个,文件流就能正常合并在一个文件里了。


当然,关于这个同名文件上传改名的操作,后端应该也能完成,但是感觉过于复杂,这里就没有尝试。有兴趣的园友可以一起探讨思路。暂时就补充到这里了。

 

PS:楼主邮箱 tccwpl@163.com

目录
相关文章
|
开发框架 JavaScript 前端开发
ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件
ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件
435 0
ASP.NET Core WEB API 使用element-ui文件上传组件el-upload执行手动文件文件,并在文件上传后清空文件
|
开发框架 前端开发 .NET
ASP.NET Core单文件和多文件上传并保存到服务端
ASP.NET Core单文件和多文件上传并保存到服务端
|
开发框架 移动开发 前端开发
ASP.NET MVC中使用jQuery Ajax通过FormData对象异步提交图片文件到服务端保存并返回保存的图片路径
ASP.NET MVC中使用jQuery Ajax通过FormData对象异步提交图片文件到服务端保存并返回保存的图片路径
251 0
|
开发框架 前端开发 JavaScript
ASP.NET Core 2.1以上Bootstr ap4前端模板文件,开发环境与发布环境前端模板environment的使用
ASP.NET Core 2.1以上Bootstr ap4前端模板文件,开发环境与发布环境前端模板environment的使用
213 0
ASP.NET Core 2.1以上Bootstr ap4前端模板文件,开发环境与发布环境前端模板environment的使用
|
开发框架 .NET C#
ASP.NET Core 返回文件、用户 下载文件,从网站下载文件,动态下载文件
ASP.NET Core 返回文件、用户 下载文件,从网站下载文件,动态下载文件
497 0
|
存储 开发框架 前端开发
ASP.NET实现文件的上传和下载
最近做的一个高校网站中涉及到了上传和下载文件的需求(具体需求为:网站公布的通知,在后台要能给每个通知添加附件,在前台要能显示并下载附件),之前只是学习过关于上传的 理论知识,这里实践了一下下,与大家分享一下成果。
ASP.NET实现文件的上传和下载
|
开发框架 .NET Linux
ASP.NET Core: 十二.内置日志、使用Nlog将日志输出到文件(下)
应用离不开日志,虽然现在使用VS有强大的调试功能,开发过程中不复杂的情况懒得输出日志了(想起print和echo的有木有),但在一些复杂的过程中以及应用日常运行中的日志还是非常有用。   ASP.NET Core提供了内置的日志,但没弄明白这么把它输出到文件, 只能在VS的输出中查看, 谁知道怎么弄告诉我一下。
268 0
|
开发框架 .NET C++
ASP.NET Core: 十二.内置日志、使用Nlog将日志输出到文件(上)
应用离不开日志,虽然现在使用VS有强大的调试功能,开发过程中不复杂的情况懒得输出日志了(想起print和echo的有木有),但在一些复杂的过程中以及应用日常运行中的日志还是非常有用。   ASP.NET Core提供了内置的日志,但没弄明白这么把它输出到文件, 只能在VS的输出中查看, 谁知道怎么弄告诉我一下。
394 0
ASP.NET Core: 十二.内置日志、使用Nlog将日志输出到文件(上)
|
XML 开发框架 .NET
【原创】ASP.NET WebApi接收xml文件 xml序列化
如何新建WebApi项目就不用我介绍了吧。 直接进入正题。 首先,在.net平台不论要接收什么,肯定是从Request里获取。 大家肯定对普通的参数获取非常熟悉了,下面就介绍一下如何从Request获取文件流. System.IO.Stream sm =Request.Content.ReadAsStreamAsync().Result 这个方法返回的是一个System.IO.Stream类型,如果是单纯想获得文件,到这一步你就可以把它保存到本地了。
9110 0