WEB上传大文件解决方案

众所皆知,web上传大文件,一直是一个痛。上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的。

本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路。下面贴出简易DEMO源码分享:

前端页面:

@{
    ViewBag.Title = "Upload";
}
<h2>Upload</h2>
<table class="table table-striped">
    <tr>
        <td><input type="file" id="file"  onchange="selfile()" /></td>
        <td><input type="button" value="上传" onclick="uploading()" /></td>
    </tr>
    <tr>
        <td colspan="2">文件信息:<span id="fileMsg"></span></td>
    </tr>
    <tr>
        <td colspan="2">当前进度:<span id="upsize"></span></td>
    </tr>
</table>
<script src="~/Scripts/myUploader.js"></script>
<script type="text/javascript">
   //guid
    var guid = "@Guid.NewGuid()";
    var uploader;
    function selfile() {
        var f =  $("#file")[0].files[0];
        uploader = new SupperUploader("@Url.Action("RecvUpload")", f, guid, (1024*1024));
        $("#fileMsg").text("文件名:" + uploader.fileName + "文件类型:" + uploader.fileType + "文件大小:" + uploader.fileSize + "字节");
    }
    function uploading() {
        uploader.UploadFun(function () {
            $("#upsize").text(uploader.upedSize);
        })
    }
</script>
SupperUploader是我自己封装的JS插件,源码如下:

 

var SupperUploader = function (uploadUrl, file, guid, cutSize) {
    this.file = file;
    //文件大小
    this.fileSize = file.size;
    //文件类型
    this.fileType = file.type;
    //文件路径
    this.fileName = file.name;
    //guid
    this.guid = guid;
    //分片大小
    this.cutSize = cutSize,
    //已上传
    this.upedSize = 0;
    //开始位置
    this.startIndex = 0;
    //结束位置
    this.endIndex = 0;
    //序号
    this.indexr = 0;
    //上传路径
    this.uploadUrl = uploadUrl;
    //合并结果
    this.merged = false;
};
SupperUploader.prototype = {
    UploadFun: function (uploadCallBack) {
        if (this.merged) 
            return;
        var thisobj = this;
        $.ajax({
            type: "POST",
            url: thisobj.uploadUrl,
            enctype: 'multipart/form-data',
            data: thisobj.CutFileFun(),
            processData: false,
            contentType: false,
            success: function (res) {
                if (res == "success") {
                    if (thisobj.upedSize == thisobj.fileSize) {
                        thisobj.merged = true;
                        alert("已成功上传!")
                        return;
                    }
                    thisobj.upedSize += thisobj.cutSize;
                    if (thisobj.upedSize > thisobj.fileSize)
                        thisobj.upedSize = thisobj.fileSize;
                    thisobj.indexr+=1;
                    //执行回调函数
                    uploadCallBack();
                    //继续调用上传
                    thisobj.UploadFun(uploadCallBack);
                }
            }
        });
    },
    CutFileFun: function () {
        var formData = null;
        if (this.upedSize < this.fileSize) {
            this.startIndex = this.upedSize;
            this.endIndex = this.startIndex + this.cutSize;
            if (this.endIndex > this.fileSize) {
                this.endIndex = this.fileSize;
            }
            var currentData = this.file.slice(this.startIndex, this.endIndex);
            formData = new FormData();
            formData.append("file", currentData);
            formData.append("index", this.indexr);
            formData.append("fname", this.fileName);
            formData.append("guid", this.guid);
            formData.append("ismerge", this.fileSize == this.endIndex);
            
        }
        return formData;
    }
};
后端代码,此Demo是基于MVC架构的:
        [HttpGet]
        public ActionResult Upload() {
            return View();
        }

        [HttpPost]
        public ActionResult RecvUpload(){
            try
            {
                string fileName = Request["fname"];
                string index = Request["index"];
                string guid = Request["guid"];
                var file = Request.Files[0];
                var ismerge = Request["ismerge"];
                string tempDirpath = "~/Content/temp/" + guid + "/";
                string savepath = tempDirpath + index + "_" + fileName;
                //合并文件
                if (bool.Parse(ismerge))
                {
                    //获取所有分割文件
                    var files = System.IO.Directory.GetFiles(Server.MapPath(tempDirpath));
                    //文件FILEINFO
                    var infos = files.Select(x => new FileInfo(x)).ToList().OrderBy(x=>x.LastWriteTime).ToList();
                    //合并文件流
                    FileStream mergefs = new FileStream(Server.MapPath("~/Content/temp/" + fileName),FileMode.Append);
                    BinaryWriter bw = new BinaryWriter(mergefs);
                    FileStream tempfs = null;
                    BinaryReader tempbr= null;
                    infos.ToList().ForEach(f =>
                    {
                        tempfs = new FileStream(f.FullName, FileMode.Open);
                        tempbr = new BinaryReader(tempfs);
                        bw.Write(tempbr.ReadBytes((int)tempfs.Length));
                        tempfs.Close();
                        tempbr.Close();
                    });
                    bw.Close();
                    mergefs.Close();
                    //删除分块文件
                    infos.ForEach(f =>{
                        System.IO.File.Delete(f.FullName);

                    });
                    return Json("success");
                }
                if (!System.IO.Directory.Exists(Server.MapPath(tempDirpath))){
                    System.IO.Directory.CreateDirectory(Server.MapPath(tempDirpath));
                }
                using (FileStream fs = new FileStream(Server.MapPath(savepath), FileMode.CreateNew))
                {

                    using (Stream stream = file.InputStream)
                    {
                        byte[] buffer = new byte[stream.Length];
                        stream.Read(buffer, 0, (int)stream.Length);
                        fs.Write(buffer, 0, buffer.Length);
                    }
                }
                return Json("success");

            }
            catch (Exception e)
            {

                return Json(e.Message);
            }
            
        }

在此分享!希望多多指正~

 

 

posted on 2018-05-21 17:24  潇潇@暮雨  阅读(3812)  评论(0编辑  收藏  举报

导航