zoukankan      html  css  js  c++  java
  • 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);
                }
                
            }
    
    

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

     
  • 相关阅读:
    Microsoft Web Camp
    [程序员学英语]26个英文字母
    原来接口是这样用的!一个例子搞定接口
    BizTalk Server 2010 培训
    [PM Tools]软件项目进度跟踪表v4.0
    BizTalk 开发系列(四十一) BizTalk 2010 BAM 安装手记
    WCF服务编程HelloWorld
    BizTalk 开发系列(三十九) BizTalk Server 2009技术概览
    WCF服务编程WCF应用程序的消息跟踪
    WCF服务编程基础
  • 原文地址:https://www.cnblogs.com/paulcode/p/9068326.html
Copyright © 2011-2022 走看看