asp.net 分片上传

  在之前写上传的时候都是直接将文件通过file标签提交到后台,这样操作可以,但是响应时间会很长,而且文件一旦过大,会需要配置文件,这里就需要用到分片的功能,在网上找了一个demo照着做之后感觉还可以。

参照的地址:https://www.cnblogs.com/sunshine-wy/p/10681765.html   里面已经讲的十分详细了。我只是搬过来记录一下

  我之前做的是在后台进行分片,现在的这个demo是在前台分片,分好了再通过ajax 依次上传,到后台进行拼接,这样的好处是很多的,比如添加进度条,做断点续传。还能减轻服务器的压力

前台代码:

<!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>
View Code

后台接收:

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;
            }
        }
    }
}
View Code

  按照默卿的测试 ,这样接收还有一点问题:“从demo上讲,上面的案例基本没有问题,但是实际使用的场景中,会存在这样一个问题,由于文件是存在磁盘上的,当用户再次上传同名文件时,文件流会被继续追加到这个文件里,而不是另起一个文件,或者做覆盖操作,因为FileMode.Append模式下会检测当前路径是否存在这个文件,存在则append。那么该如何解决这个问题呢,一开始我想到的是通过size判断,如果传入文件的size,不等于读取到的文件流对象的大小,则说明文件还没有传输完毕,则可以继续append。但是当等于时,是需要新建文件的,所以就得重命名了,windows系统再重命名的时候会在原有文件名后面带上副本啊之类的名称,我这里为了简洁,直接在前端读取了一个系统时间作为唯一标识,来混入文件名,这样后台保存的文件就不会存在文件流并入一个文件的问题了。

 

  

posted @ 2020-05-13 12:05  保护青蛙  阅读(295)  评论(0编辑  收藏  举报