• 上传插件(WebUploader)


    官网:http://fex.baidu.com/webuploader/
    插件下载:https://github.com/fex-team/webuploader/releases/download/0.1.5/webuploader-0.1.5.zip
    下面开始对WebUploader的使用
    第一种,简单粗暴
    前端代码:

    <div id="picker">选择文件</div>
    <button id="ctlBtn" class="btn btn-default">开始上传</button>
    <!--引用webuploader的js和css-->
    <link href="~/Scripts/webuploader-0.1.5/webuploader.css" rel="stylesheet" />
    <script src="~/Scripts/webuploader-0.1.5/webuploader.js"></script>
    <script type="text/javascript">
        var uploader = WebUploader.create({
    
            // (如果是新浏览器 可以不用 flash)
            //swf: '/Scripts/webuploader-0.1.5/Uploader.swf',
    
            // 文件接收服务端。
            server: '/Webuploader/SaveFile',
    
            // 选择文件的按钮。可选。
            // 内部根据当前运行是创建,可能是input元素,也可能是flash.
            pick: '#picker'
        });
    
        $("#ctlBtn").click(function () {
            uploader.upload();
        });
    
        uploader.on('uploadSuccess', function (file) {
            alert("上传成功");
        });
    
    </script>
    

      后台代码:

    public string SaveFile()
    {
        if (Request.Files.Count > 0)
        {
            Request.Files[0].SaveAs(Server.MapPath("~/App_Data/") + Path.GetFileName(Request.Files[0].FileName));
            return "保存成功";
        }
        return "没有读到文件";
    }
    

      第二种,分片上传。和我们之前自己写的效果差不多。
    前端代码:

    var uploader = WebUploader.create({ 
        //兼容老版本IE
        swf: '/Scripts/webuploader-0.1.5/Uploader.swf', 
        // 文件接收服务端。
        server: '/Webuploader/SveFile2', 
        // 开起分片上传。
        chunked: true, 
        //分片大小
        chunkSize: 1000000, 
        //上传并发数
        threads: 1,
        // 选择文件的按钮。 
        pick: '#picker'
    });
    
    // 点击触发上传
    $("#ctlBtn").click(function () {
        uploader.upload();
    });
    
    uploader.on('uploadSuccess', function (file) {
        alert("上传成功");
    });
    

      后台代码:

    public string SveFile2()
    {
        //保存文件到根目录 App_Data + 获取文件名称和格式
        var filePath = Server.MapPath("~/App_Data/") + Path.GetFileName(Request.Files[0].FileName);
        //创建一个追加(FileMode.Append)方式的文件流
        using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write))
        {
            using (BinaryWriter bw = new BinaryWriter(fs))
            {
                //读取文件流
                BinaryReader br = new BinaryReader(Request.Files[0].InputStream);
                //将文件留转成字节数组
                byte[] bytes = br.ReadBytes((int)Request.Files[0].InputStream.Length);
                //将字节数组追加到文件
                bw.Write(bytes);
            }
        }
        return "保存成功";
    }
    

      我们看到了有个参数threads: 1上传并发数,如果我们改成大于1会怎样?前端会同时发起多个文件片上传。后台就会报错,多个进程同时操作一个文件。
    那如果我们想要多线程上传怎么办?改代码吧(主要是后台逻辑)。
    前端代码:

    //并发上传(多线程上传)
    var uploader = WebUploader.create({
        //兼容老版本IE
        swf: '/Scripts/webuploader-0.1.5/Uploader.swf',
        // 文件接收服务端。
        server: '/Webuploader/SveFile3',
        // 开起分片上传。
        chunked: true,
        //分片大小
        chunkSize: 1000000,
        //上传并发数
        threads: 10,
        // 选择文件的按钮。
        pick: '#picker'
    });
    
    // 点击触发上传
    $("#ctlBtn").click(function () {
        uploader.upload();
    });
    
    uploader.on('uploadSuccess', function (file) {
        //上传完成后,给后台发送一个合并文件的命令
        $.ajax({
            url: "/Webuploader/FileMerge",
            data: { "fileName": file.name },
            type: "post",
            success: function () {
                alert("上传成功");
            }
        });
    });
    

      后台代码:

    public string SveFile3()
    {
        var chunk = Request.Form["chunk"];//当前是第多少片 
    
        var path = Server.MapPath("~/App_Data/") + Path.GetFileNameWithoutExtension(Request.Files
        if (!Directory.Exists(path))//判断是否存在此路径,如果不存在则创建
        {
            Directory.CreateDirectory(path);
        }
        //保存文件到根目录 App_Data + 获取文件名称和格式
        var filePath = path + "/" + chunk;
        //创建一个追加(FileMode.Append)方式的文件流
        using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write))
        {
            using (BinaryWriter bw = new BinaryWriter(fs))
            {
                //读取文件流
                BinaryReader br = new BinaryReader(Request.Files[0].InputStream);
                //将文件留转成字节数组
                byte[] bytes = br.ReadBytes((int)Request.Files[0].InputStream.Length);
                //将字节数组追加到文件
                bw.Write(bytes);
            }
        }           
        return "保存成功";
    }
    /// <summary>
    /// 合并文件
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public bool FileMerge()
    {
        var fileName = Request.Form["fileName"];
        var path = Server.MapPath("~/App_Data/") + Path.GetFileNameWithoutExtension(fileName);
    
        //这里排序一定要正确,转成数字后排序(字符串会按1 10 11排序,默认10比2小)
        foreach (var filePath in Directory.GetFiles(path).OrderBy(t => int.Parse(Path.GetFileNameWithoutExtension(t))))
        {
            using (FileStream fs = new FileStream(Server.MapPath("~/App_Data/") + fileName, FileMode.Append, FileAccess.Write))
            {
                byte[] bytes = System.IO.File.ReadAllBytes(filePath);//读取文件到字节数组
                fs.Write(bytes, 0, bytes.Length);//写入文件
            }
            System.IO.File.Delete(filePath);
        }
        Directory.Delete(path);
        return true;
    }
    

      到这里你以为就结束了吗?错,还有好多情况没有考虑到。如果多个用户上传的文件名字一样会怎样?如何实现断点续传?还没实现选择多个文件?不过,这里不打算继续贴代码了(再贴下去,代码量越来越多了),自己也来练习练习吧。
    提供一个思路,上传前先往数据库插入一条数据。数据包含文件要存的路径、文件名(用GUID命名,防止同名文件冲突)、文件MD5(用来识别下次续传和秒传)、临时文件块存放路径、文件是否完整上传成功等信息。
    然后如果我们断网后再传,首先获取文件MD5值,看数据库里面有没上传完成的文件,如果有就实现秒传。如果没有,看是不是有上传了部分的。如果有接着传,如果没有则重新传一个新的文件。

  • 相关阅读:
    windows phone7 学习笔记08——屏幕方向
    windows phone7 学习笔记07——系统托盘和应用程序栏
    .Net中获取当前路径的方法
    开始》运行 常用打开程序命令
    C#操作API
    WinForm 皮肤 IrisSkin
    Visual Studio 2005 无法显示设计视图的解决方法
    SQL Server脏读方式数据提取NOLOCK和READPAST
    在存储过程中设置某表的触发器是否启用
    ajax读取XML文件并显示到下拉列表框中
  • 原文地址:https://www.cnblogs.com/fjzhang/p/7227494.html
Copyright © 2020-2023  润新知