首页 > 代码库 > 上传插件(WebUploader)

上传插件(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="http://www.mamicode.com/~/Scripts/webuploader-0.1.5/webuploader.css" rel="stylesheet" /><script src="http://www.mamicode.com/~/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值,看数据库里面有没上传完成的文件,如果有就实现秒传。如果没有,看是不是有上传了部分的。如果有接着传,如果没有则重新传一个新的文件。

上传插件(WebUploader)