写在前面:

               项目需要  , 以前 做过一个单文件在2G以下  可以多个文件上传至服务器的功能,客户 不满足, 参考了很多前辈们的代码,在网上也找了不少 ,然后总结出来了一个 ,做一下总结。

 


aspx:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <link href="css/flieUpoload.css" rel="stylesheet" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <div class="container">
                <input type="file" name="fileselect" id="fileselect" value="" multiple />
                <input type="button" id="btnselect" value="选择上传的文件" />
                <input type="button" id="btnupload" value="开始上传" />
            </div>
             <table cellspacing="0" cellpadding="0" id="filelist">
                <tr>
                    <td class="filename">文件名</td>
                    <td class="fileprogress">进度</td>
                    <td class="filestatus">状态</td>
                </tr>
                <tr id="trmsg">
                    <td colspan="3" id="tdmsg">请选择要上传的文件</td>
                </tr>
            </table>
            <script src="js/jquery-1.10.2.min.js"></script>
            <script src="js/spark-md5.min.js"></script>
            <script src="js/FileUpoload.js"></script>
        </div>
    </form>
</body>
</html>
View Code

css:

*{
    font-family: "微软雅黑";
    margin: 0;
    padding: 0;
}

.container {
    padding-top: 10px;
    padding-left: 10px;
}

    .container input {
        width: 120px;
        height: 30px;
        background-color: blue;
        color: white;
        border: 0;
        line-height: 30px;
        border-radius: 5px;
        margin-right: 5px;
        outline: none;
        cursor: pointer;
    }

#filelist {
    width: 800px;
    border: solid 1px #eee;
    border-collapse: collapse;
    margin: 10px;
}

    #filelist td {
        border-bottom: solid 1px #eee;
        height: 30px;
        font-size: 12px;
        padding: 0 3px;
    }

.filename {
    width: 200px;
    text-align: center;
}

.filestatus {
    width: 100px;
    text-align: center;
}

.fileprogress {
    text-align: center;
}

.domprogress {
    width: 320px;
}

.domsize {
    display: block;
}

#tdmsg {
    text-align: center;
}

#fileselect {
    display: none;
}

span.domtime {
    display: block;
}
View Code

js:

$("#btnselect").click(function () {
    $("#fileselect").click();
});
$("#fileselect").change(function () {
    var files = this.files;
    if (files.length > 0) {
        $("#trmsg").remove();
        $(files).each(function (index, item) {
            console.log(index, item);
            var filesize = 0;
            if ((item.size / 1024 / 1024 / 1024) >= 1) {
                filesize = (item.size / 1024 / 1024 / 1024).toFixed(2) + "GB"; // b=>kb=>mb=>gb
            } else if ((item.size / 1024 / 1024 / 1024) < 1 && (item.size / 1024 / 1024) >= 1) {
                filesize = (item.size / 1024 / 1024).toFixed(2) + "MB";
            } else if ((item.size / 1024 / 1024) < 1 && (item.size / 1024) >= 1) {
                filesize = (item.size / 1024).toFixed(2) + "KB";
            } else {
                filesize = item.size + "B";
            }

            var htmlstr = '<tr><td>' + item.name + '</td><td><progress value="0" max="100" class="domprogress"></progress><span class="dompercent"> 0/' + filesize + '</span><span class="domtime">总共耗时:0 秒</span></td><td class="filestatus"><span class="domstatus">排队中</span></td></tr>';
            $("#filelist").append(htmlstr);

        });

    }

});
$.ajaxSetup({
    async: false
});
$("#btnupload").click(function () {

    var files = $("#fileselect")[0].files;
    $.ajaxSettings.async = false;
    $(files).each(function (index, item) {
        yyupload(files[index], $("span.domstatus").eq(index), $("span.dompercent").eq(index), $(".domprogress").eq(index), $("span.domtime").eq(index));
    });
    $.ajaxSettings.async = true;
});

//文件上传
function yyupload(file, dommsg, dompercentmb, domprogress, domtime, fn) {
    var startTime = new Date();
    //获取文件的md5字符串,用于标识文件的唯一性。
    calculate(file);
    //获取文件的加密字符串
    function calculate(file) {
        var fileReader = new FileReader();
        var chunkSize = 1024 * 1024 * 5; //每次读取5MB
        var chunksCount = Math.ceil(file.size / chunkSize); //回大于参数x的最小整数 8=》8  8.4=》9  8.5=》9 -8.5=》-8
        var currentChunk = 0; //当前块的索引
        var spark = new SparkMD5();
        fileReader.onload = function (e) {
            //console.log((currentChunk + 1) + "/" + chunksCount)
            dommsg.text("正在检查文件: " + (currentChunk + 1) + "/" + chunksCount);
            spark.appendBinary(e.target.result); // 添加二进制字符串
            currentChunk++;
            if (currentChunk < chunksCount) {
                loadNext();
            } else {
                var md5value = spark.end();
                //console.log("文件加密结束,密钥为:" + md5value);
                checkfile(md5value, file); //检查服务器是否存在该文件,存在就从断点继续上传
            }
        };

        function loadNext() {
            var start = currentChunk * chunkSize; //计算读取开始位置
            var end = start + chunkSize >= file.size ? file.size : start + chunkSize; //计算读取结束位置
            fileReader.readAsText(file.slice(start, end)); //读取为二进制字符串readAsBinaryString
        };
        loadNext();
    }

    var repeatcount = 0;
    //检查文件是否已经存在
    function checkfile(md5value, file) {
        //var Id = GetQueryString("Id");
        $.ajaxSettings.async = false;
        var fd = new FormData();
        fd.append('rquesttype', "chekcfile");
        fd.append('filename', file.name);
        fd.append('md5value', md5value);
        //fd.append('type', GetQueryString("type"))
        //fd.append('Id', Id);
        var xhr = new XMLHttpRequest();
        xhr.open('post', 'FileUpoload.ashx', true);
        xhr.onreadystatechange = function (res) {
            if (xhr.readyState == 4 && xhr.status == 200) {
                var jsonobj = JSON.parse(xhr.responseText); //可以将json字符串转换成json对象  //JSON.stringify(jsonobj); //可以将json对象转换成json对符串
                console.log("继续上传的位置:" + jsonobj.startindex);
                switch (jsonobj.flag) {
                    case "0":
                        doUpload(md5value, file, 0);
                        break;
                    case "1":
                        doUpload(md5value, file, parseInt(jsonobj.startindex));
                        break;
                    case "2":

                        secondUpload(file);
                        domtime.text("此文件已经存在,无法继续上传。");
                        break;
                }
                repeatcount = 0;
            } else if (xhr.status == 500) {
                setTimeout(function () {
                    if (repeatcount < 3) {
                        checkfile(md5value, file);
                    }
                    repeatcount++;
                }, 3000);
            }
        }
        //开始发送
        xhr.send(fd);
        $.ajaxSettings.async = true;
    }

    function secondUpload(file) {
        var timerange = (new Date().getTime() - startTime.getTime()) / 1000;
        domtime.text("耗时" + timerange + "");
        //显示结果进度
        var percent = 100;
        dommsg.text(percent.toFixed(2) + "%");
        domprogress.val(percent);
        var total = file.size;
        if (total > 1024 * 1024 * 1024) {
            dompercentmb.text((total / 1024 / 1024 / 1024).toFixed(2) + "GB/" + (total / 1024 / 1024 / 1024).toFixed(2) + "GB");
        } else if (total > 1024 * 1024) {
            dompercentmb.text((total / 1024 / 1024).toFixed(2) + "MB/" + (total / 1024 / 1024).toFixed(2) + "MB");
        } else if (total > 1024 && total < 1024 * 1024) {
            dompercentmb.text((total / 1024).toFixed(2) + "KB/" + (total / 1024).toFixed(2) + "KB");
        } else {
            dompercentmb.text((total).toFixed(2) + "B/" + (total).toFixed(2) + "B");
        }

    }

    //上传文件
    function doUpload(md5value, file, startindex) {
        var reader = new FileReader()
        var step = 1024 * 200;
        var cuLoaded = startindex;
        var total = file.size;
        //读取一段成功
        reader.onload = function (e) {
            //处理读取的结果
            var result = reader.result; //本次读取的数据
            var loaded = e.loaded; //本次读取的数据长度
            uploadFile(result, cuLoaded, function () { //将分段数据上传到服务器
                cuLoaded += loaded; //如果没有读完,继续
                var timerange = (new Date().getTime() - startTime.getTime()) / 1000;
                if (total > 1024 * 1024 * 1024) {
                    dompercentmb.text((cuLoaded / 1024 / 1024 / 1024).toFixed(2) + "GB/" + (total / 1024 / 1024 / 1024).toFixed(2) + "GB");
                } else if (total > 1024 * 1024) {
                    dompercentmb.text((cuLoaded / 1024 / 1024).toFixed(2) + "MB/" + (total / 1024 / 1024).toFixed(2) + "MB");
                } else if (total > 1024 && total < 1024 * 1024) {
                    dompercentmb.text((cuLoaded / 1024).toFixed(2) + "KB/" + (total / 1024).toFixed(2) + "KB");
                } else {
                    dompercentmb.text((cuLoaded).toFixed(2) + "B/" + (total).toFixed(2) + "B");
                }

                domtime.text("耗时" + timerange + "");
                if (cuLoaded < total) {
                    readBlob(cuLoaded);
                } else {
                    console.log('总共用时:' + timerange);
                    cuLoaded = total;
                    sendfinish(); //告知服务器上传完毕  
                    domtime.text("上传完成,总共耗时" + timerange + "");
                }
                //显示结果进度
                var percent = (cuLoaded / total) * 100;
                dommsg.text(percent.toFixed(2) + "%");
                domprogress.val(percent);
            });
        }
        var k = 0;
        function sendfinish() {
            $.ajaxSettings.async = false;
            var fd = new FormData();
            fd.append('rquesttype', "finishupload");
            fd.append('filename', file.name);
            fd.append('md5value', md5value);
            fd.append('totalsize', file.size);
            fd.append('type', GetQueryString("type"));
            fd.append('id', GetQueryString("id"));
            //fd.append('type', GetQueryString("type"))
            var xhr = new XMLHttpRequest();
            xhr.open('post', 'FileUpoload.ashx', true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    if (fn) {
                        fn(); //如果上传成功,继续上传下一个文件
                    }
                    k = 0;
                } else if (xhr.status == 500) {
                    setTimeout(function () {
                        if (k < 3) {
                            sendfinish();
                            //上传完毕的前端处理
                        }
                        k++
                    }, 3000);
                }
            }
            //开始发送
            xhr.send(fd);
            $.ajaxSettings.async = true;
        }
        var m = 0;
        //关键代码上传到服务器
        function uploadFile(result, startIndex, onSuccess) {
            var blob = new Blob([result]);
            //提交到服务器
            $.ajaxSettings.async = false;
            var fd = new FormData();
            fd.append('file', blob);
            fd.append('rquesttype', "uploadblob");
            fd.append('filename', file.name);
            fd.append('md5value', md5value);
            fd.append('loaded', startIndex);

            var xhr = new XMLHttpRequest();
            xhr.open('post', 'FileUpoload.ashx', true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    m = 0;
                    if (onSuccess)
                        onSuccess();
                } else if (xhr.status == 500) {
                    setTimeout(function () {
                        if (m < 3) {
                            containue();
                            m++;
                        }
                    }, 1000);
                }
            }
            xhr.send(fd);
            $.ajaxSettings.async = true;
        }

        function readBlob(start) {
            var blob = file.slice(start, start + step);
            reader.readAsArrayBuffer(blob);
        }
        function containue() {
            readBlob(cuLoaded);
        }
        readBlob(cuLoaded);
    }

    function GetQueryString(name) {

        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");

        var r = window.location.search.substr(1).match(reg);

        if (r != null) return unescape(r[2]); return null;

    }
}
View Code

ashx:

using Microsoft.VisualBasic.Devices;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using XLT.QC.Domain;
using XLT.QC.Entity;

namespace FTPupLoad.load
{
    /// <summary>
    /// FileUpoload 的摘要说明
    /// </summary>
    public class FileUpoload : IHttpHandler
    {

        private string basefilename = HttpContext.Current.Server.MapPath("../doc/allFile/");
        private long totalCount = 0;
        public  HttpRequest reqs;
        public void ProcessRequest(HttpContext context)
        {
            HttpRequest req = context.Request;

            string rquesttype = req.Form["rquesttype"];

            var filename = req.Form["filename"];//文件的名称

            switch (rquesttype)
            {
                case "chekcfile": chekcfile(req); break;
                case "uploadblob": uploadblob(req); break;
                case "finishupload":
                    reqs = req;
                    Task.Factory.StartNew(ThreadMethod);//解决线程并发
                    //finishupload(req);
                    break;
            }



        }
        public void ThreadMethod()
        {
            while (true)
            {
                lock (typeof(FileUpoload))
                {

                    finishupload(reqs);
                    Thread.Sleep(500);
                }
            }
        }
        /// <summary>
        /// 结束文件上传,修改上传后的名称
        /// </summary>
        /// <param name="req"></param>
        public void finishupload(HttpRequest req)
        {
            string id = req.Form["id"];
            string type = req.Form["type"];
            //接收前端传递过来的参数
            var md5value = req.Form["md5value"];//文件md5加密的字符串
            var filename = req.Form["filename"];//文件的名称
            var totalsize = req.Form["totalsize"];//文件的总大小

            string fullname = basefilename + md5value + ".part";//上传的时候的名称
            string okname = basefilename + md5value + ".ok";
            var oldname = basefilename + filename;
            Computer MyComputer = new Computer();
            try
            {
                //FileInfo okn = new FileInfo(okname);
                //if (!okn.Exists)
                //{

                File.Create(okname);
                //}
                FileInfo fi = new FileInfo(oldname);
                if (fi.Exists)
                {
                    fi.Delete();
                }
                MyComputer.FileSystem.RenameFile(fullname, filename);
            }
            catch (Exception ex)
            {

            }
            finally
            {

                ArtificialDataTitleDomain art = new ArtificialDataTitleDomain();
                ArtificialDataTitleEntity Inspect = new ArtificialDataTitleEntity();
                TestingMachineTitleDomain tmt = new TestingMachineTitleDomain();
                TestingMachineTitleEntity Repair = new TestingMachineTitleEntity();

                if (type == "Inspect")
                {
                    Inspect = art.FindByID(id);
                    if (!string.IsNullOrWhiteSpace(Inspect.docUrl))
                    {
                        Inspect.docUrl = Inspect.docUrl + filename + ",";
                    }
                    else
                    {
                        Inspect.docUrl = "allFile*" + filename + ",";
                    }

                    art.Update(Inspect);
                }
                else if (type == "Repair")
                {
                    Repair = tmt.FindByID(id);
                    if (!string.IsNullOrWhiteSpace(Repair.docUrl))
                    {
                        Repair.docUrl = Repair.docUrl + filename + ",";
                    }
                    else
                    {
                        Repair.docUrl = "allFile*" + filename + ",";
                    }
                    tmt.Update(Repair);
                }
                var str = string.Format("{{\"data\":\"ok\"}}");
                HttpContext.Current.Response.Write(str);
            }
        }


        /// <summary>
        /// 处理文件分块上传的数据
        /// </summary>
        /// <param name="req"></param>
        public void uploadblob(HttpRequest req)
        {
            if (req.Files.Count <= 0)
            {
                HttpContext.Current.Response.Write("获取服务器上传文件失败");
                return;
            }
            HttpPostedFile _file = req.Files[0];
            //获取参数
            string filename = req.Form["filename"];
            string md5value = req.Form["md5value"];

            var tempfilename = md5value + ".part";
            //如果是int 类型当文件大的时候会出问题 最大也就是 1.9999999990686774G

            long loaded = Convert.ToInt64(req.Form["loaded"]);
            totalCount += loaded;
            string newname = basefilename + tempfilename;
            Stream stream = _file.InputStream;
            if (stream.Length <= 0)
                throw new Exception("接收的数据不能为空");
            byte[] dataOne = new byte[stream.Length];
            stream.Read(dataOne, 0, dataOne.Length);
            FileStream fs;
            try
            {
                fs = new FileStream(newname, FileMode.Append, FileAccess.Write, FileShare.Read, 1024);
                fs.Write(dataOne, 0, dataOne.Length);
                fs.Close();
            }
            catch (Exception ex)
            {

            }
            finally
            {
                stream.Close();
                //检查文件已经上传的大小是否等于文件的总大小
            }
            HttpContext.Current.Response.Write("分段数据保存成功");
        }

        /// <summary>
        /// 检查文件是否存在
        /// </summary>
        /// <param name="req"></param>
        public void chekcfile(HttpRequest req)
        {
            var md5value = req.Form["md5value"];//得到前端传递过来的文件的mdf字符串
            var path_ok = basefilename + md5value + ".ok";
            var path_part = basefilename + md5value + ".part";
            int flag = 0;
            string json = string.Empty;
            if (File.Exists(path_ok))//传完了
            {

                flag = 2;
                json = string.Format("{{\"flag\":\"{0}\"}}", flag);
            }
            else if (File.Exists(path_part))//传了一部分
            {
                flag = 1;
                var startindex = new FileInfo(path_part).Length.ToString();
                json = string.Format("{{\"flag\":\"{0}\",\"startindex\":\"{1}\"}}", flag, startindex);
            }
            else//新文件
            {
                flag = 0;
                json = string.Format("{{\"flag\":\"{0}\",\"startindex\":\"0\"}}", flag);
            }
            HttpContext.Current.Response.Write(json);
        }


        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}
View Code