asp. net core block upload file example

  • 2021-09-12 00:57:43
  • OfStack

After writing asp. net multi-file upload, I feel that this upload still has many defects, so. . . (Omit 10,000 words, no nonsense). Here, I didn't use the traditional asp. net, but chose the open source asp. net core for the simple reason that net core is the new beginning of net and the future of net and net developers. I hope net will develop better and better (everyone's salary is getting higher and higher).

1. Implementation of the front end:

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=" Please select a file " size="20" name="upfile" id="upfile" style="border:1px dotted #ccc">
      <input type="button" value=" Browse " 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"> Start uploading </button>
    </div>
    <div class="col-lg-4"></div>
  </div>
</body>
</html>

2). javascript:


var UploadPath = "";
// Start uploading 
function UploadStart() {
  var file = $("#path")[0].files[0];
  AjaxFile(file, 0);
}
function AjaxFile(file, i) {
  var name = file.name, // Filename 
  size = file.size, // Total size shardSize = 2 * 1024 * 1024, 
  shardSize = 2 * 1024 * 1024,// With 2MB For 1 Pieces 
  shardCount = Math.ceil(size / shardSize); // Total number of slices 
  if (i >= shardCount) {
    return;
  }
  // Calculate every 1 Start and end positions of slices 
  var start = i * shardSize,
  end = Math.min(size, start + shardSize);
  // Structure 1 A form, FormData Yes HTML5 Added 
  var form = new FormData();
  form.append("data", file.slice(start, end)); //slice Method is used to cut out the 1 Part 
  form.append("lastModified", file.lastModified);
  form.append("fileName", name);
  form.append("total", shardCount); // Total number of slices 
  form.append("index", i + 1); // What is the current slice 
  UploadPath = file.lastModified
  //Ajax Submission of documents 
  $.ajax({
    url: "/Upload/UploadFile",
    type: "POST",
    data: form,
    async: true, // Asynchronous 
    processData: false, // It's important, tell me jquery Don't be right form Process 
    contentType: false, // Important, specified as false To form the correct 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();// Empty input file
          $('#upfile').val(' Please select a file ');
          alert("success!!!");
        }
      }
    }
  });
}

The main idea here is to use the slice method of html5 File api to divide the file into blocks, then new1 FormData () objects are used to store the file data, and then the AjaxFile method is called recursively until the upload is finished.

2. Background 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:\ Browser ", lastModified);// Temporarily save the directory of blocks 
      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);// Delete Folder 
        throw ex;
      }
    }

    public async Task<bool> FileMerge(string lastModified,string fileName)
    {
      bool ok = false;
      try
      {
        var temporary = Path.Combine(@"E:\ Browser ", lastModified);// Temporary folder 
        fileName = Request.Form["fileName"];// Filename 
        string fileExt = Path.GetExtension(fileName);// Get the file suffix 
        var files = Directory.GetFiles(temporary);// Get all the following files 
        var finalPath = Path.Combine(@"E:\ Browser ", DateTime.Now.ToString("yyMMddHHmmss") + fileExt);// The final file name ( demo The file name when it is uploaded is saved in, and the actual operation must not be like this) 
        var fs = new FileStream(finalPath, FileMode.Create);
        foreach (var part in files.OrderBy(x => x.Length).ThenBy(x => x))// Platoon 1 In the next order, ensure that from 0-N Write
        {
          var bytes = System.IO.File.ReadAllBytes(part);
          await fs.WriteAsync(bytes, 0, bytes.Length);
          bytes = null;
          System.IO.File.Delete(part);// Delete a block 
        }
        fs.Close();
        Directory.Delete(temporary);// Delete Folder 
        ok = true;
      }
      catch (Exception ex)
      {
        throw ex;
      }
      return ok;
    }

  }
}


The idea here is to save every 1 block file to a temporary folder, and finally merge these temporary files through FileStream (the merge must be in order). The background methods are asynchronous (async await is really very easy to use). Although I don't know if the efficiency has been improved, I just think it is cool.

Source download: DotNet_jb51.rar


Related articles: