当前位置: 移动技术网 > IT编程>开发语言>.net > asp.net core分块上传文件示例

asp.net core分块上传文件示例

2017年12月08日  | 移动技术网IT编程  | 我要评论

贺兰雪txt,协和创美,元智快递

写完asp.net多文件上传后,感觉这种上传还是有很多缺陷,于是。。。(省略一万字,不废话)。这里我没用传统的asp.net,而选择了开源的asp.net core,原因很简单,.net core是.net新的开始,更是.net和.net开发者的未来,希望.net发展越来越好(大家的工资越来越高(●ˇ∀ˇ●))。

1.前端的实现:

1).html: 

<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>index</title>
  <link href="/lib/bootstrap/dist/css/bootstrap.css" rel="external nofollow" rel="stylesheet" />
  <script src="/lib/jquery/dist/jquery.js"></script>
  <script src="/lib/bootstrap/dist/js/bootstrap.js"></script>
  <script src="/js/uploadjs.js"></script>
</head>
<body>
  <div class="row" style="margin-top:20%">
    <div class="col-lg-4"></div>
    <div class="col-lg-4">
      <input type="text" value="请选择文件" size="20" name="upfile" id="upfile" style="border:1px dotted #ccc">
      <input type="button" value="浏览" onclick="path.click()" style="border:1px solid #ccc;background:#fff">
      <input type="file" id="path" style="display:none" multiple="multiple" onchange="upfile.value=this.value">
      <br />
      <span id="output">0%</span>
      <button type="button" id="file" onclick="uploadstart()" style="border:1px solid #ccc;background:#fff">开始上传</button>
    </div>
    <div class="col-lg-4"></div>
  </div>
</body>
</html>

2).javascript:

var uploadpath = "";
//开始上传
function uploadstart() {
  var file = $("#path")[0].files[0];
  ajaxfile(file, 0);
}
function ajaxfile(file, i) {
  var name = file.name, //文件名
  size = file.size, //总大小shardsize = 2 * 1024 * 1024, 
  shardsize = 2 * 1024 * 1024,//以2mb为一个分片
  shardcount = math.ceil(size / shardsize); //总片数
  if (i >= shardcount) {
    return;
  }
  //计算每一片的起始与结束位置
  var start = i * shardsize,
  end = math.min(size, start + shardsize);
  //构造一个表单,formdata是html5新增的
  var form = new formdata();
  form.append("data", file.slice(start, end)); //slice方法用于切出文件的一部分
  form.append("lastmodified", file.lastmodified);
  form.append("filename", name);
  form.append("total", shardcount); //总片数
  form.append("index", i + 1); //当前是第几片
  uploadpath = file.lastmodified
  //ajax提交文件
  $.ajax({
    url: "/upload/uploadfile",
    type: "post",
    data: form,
    async: true, //异步
    processdata: false, //很重要,告诉jquery不要对form进行处理
    contenttype: false, //很重要,指定为false才能形成正确的content-type
    success: function (result) {
      if (result != null) {
        i = result.number++;
        var num = math.ceil(i * 100 / shardcount);
        $("#output").text(num + '%');
        ajaxfile(file, i);
        if (result.mergeok) {
          var filepath = $("#path");
          filepath.after(filepath.clone().val(""));
          filepath.remove();//清空input file
          $('#upfile').val('请选择文件');
          alert("success!!!");
        }
      }
    }
  });
}

这里的主要思路是利用html5 file api的slice方法把文件分块,然后new一个formdata()对象用于储存文件数据,之后就是递归调用ajaxfile方法直至上传完毕。

2.后台c#:

using system;
using system.collections.generic;
using system.linq;
using system.threading.tasks;
using microsoft.aspnetcore.mvc;
using system.io;

// for more information on enabling mvc for empty projects, visit http://go.microsoft.com/fwlink/?linkid=397860

namespace dotnet.upload.controllers
{
  public class uploadcontroller : controller
  {
    // get: /<controller>/
    public iactionresult index()
    {
      return view();
    }

    [httppost]
    public async task<actionresult> uploadfile()
    {
      var data = request.form.files["data"];
      string lastmodified = request.form["lastmodified"].tostring();
      var total = request.form["total"];
      var filename = request.form["filename"];
      var index = request.form["index"];

      string temporary = path.combine(@"e:\浏览器", lastmodified);//临时保存分块的目录
      try
      {
        if (!directory.exists(temporary))
          directory.createdirectory(temporary);
        string filepath = path.combine(temporary, index.tostring());
        if (!convert.isdbnull(data))
        {
          await task.run(() => {
            filestream fs = new filestream(filepath, filemode.create);
            data.copyto(fs);
          });
        }
        bool mergeok = false;
        if (total == index)
        {
          mergeok = await filemerge(lastmodified, filename);
        }

        dictionary<string, object> result = new dictionary<string, object>();
        result.add("number", index);
        result.add("mergeok", mergeok);
        return json(result);

      }
      catch (exception ex)
      {
        directory.delete(temporary);//删除文件夹
        throw ex;
      }
    }

    public async task<bool> filemerge(string lastmodified,string filename)
    {
      bool ok = false;
      try
      {
        var temporary = path.combine(@"e:\浏览器", lastmodified);//临时文件夹
        filename = request.form["filename"];//文件名
        string fileext = path.getextension(filename);//获取文件后缀
        var files = directory.getfiles(temporary);//获得下面的所有文件
        var finalpath = path.combine(@"e:\浏览器", datetime.now.tostring("yymmddhhmmss") + fileext);//最终的文件名(demo中保存的是它上传时候的文件名,实际操作肯定不能这样)
        var fs = new filestream(finalpath, filemode.create);
        foreach (var part in files.orderby(x => x.length).thenby(x => x))//排一下序,保证从0-n write
        {
          var bytes = system.io.file.readallbytes(part);
          await fs.writeasync(bytes, 0, bytes.length);
          bytes = null;
          system.io.file.delete(part);//删除分块
        }
        fs.close();
        directory.delete(temporary);//删除文件夹
        ok = true;
      }
      catch (exception ex)
      {
        throw ex;
      }
      return ok;
    }

  }
}


这里的思路就是先保存每一个分块的文件到一个临时文件夹,最后再通过filestream合并这些临时文件(合并时必需要按顺序)。后台的方法都进行了异步化(async await真的非常好用),虽然不知道对效率有没有提升,但是就是觉得这样很酷。

源码下载:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网