[筆記]Dotnet Core C# 大檔案切塊上傳(file chunk upload)

檔案太大無法一次上傳,切分成小塊後再分次上傳到Server

upload large files in ASP.NET Core

divide the large file be chunks and upload

 

HTML部分
<!--沒錯就是這麼簡單-->
<input type="file" id="bigfile" />

<script src="~/lib/jquery/dist/jquery.min.js"></script>
JS部分
$(document).on("change", "#bigfile", function () {

    uploadFile($("#bigfile")[0].files[0]);
});

function uploadFile(file) {
    //把檔案切塊(file chunk)每塊最大不超過100KB
    var maxFileSizeKB = 100;

    var fileChunks = [];
    var bufferChunkSizeInBytes = maxFileSizeKB * (1024);

    var currentStreamPosition = 0;
    var endPosition = bufferChunkSizeInBytes;
    var size = file.size;

    while (currentStreamPosition < size) {
        fileChunks.push(file.slice(currentStreamPosition, endPosition));
        currentStreamPosition = endPosition;
        endPosition = currentStreamPosition + bufferChunkSizeInBytes;
    }

    //產生Timestamp當不重複的隨機檔名
    var timestamp = new Date().getTime()
    var fileName = timestamp + "_" + file.name;
    uploadFileChunk(fileChunks, fileName, 1, fileChunks.length);

}

function uploadFileChunk(fileChunks, fileName, currentPart, totalPart) {
    var formData = new FormData();
    formData.append('file', fileChunks[currentPart - 1], fileName);

    $.ajax({
        type: "POST",
        url: '/UploadChunk/UploadFileChunks',
        contentType: false,
        processData: false,
        data: formData,
        success: function (data) {
            if (totalPart >= currentPart) {
                console.log("uploading file part no: " + currentPart, " out of " + totalPart);
                if (data.status == true) {
                    if (totalPart == currentPart) {
                        //Whole file uploaded
                        console.log("whole file uploaded successfully");
                    } else {
                        //Show uploading progress
                        uploadFileChunk(fileChunks, fileName, currentPart + 1, totalPart);
                    }
                } else {
                    //retry message to upload rest of the file
                    console.log("failed to upload file part no: " + currentPart);
                }
            }
        },
        error: function () {
            //retry message to upload rest of the file
            console("error to upload file part no: " + currentPart);
        }
    });

}
Controller部分
using Microsoft.AspNetCore.Mvc;

namespace WebUploadDemo.Controllers
{
    public class UploadChunkController : Controller
    {
        private readonly IWebHostEnvironment _env;
        public UploadChunkController(IWebHostEnvironment env)
        {
            _env = env;
        }

        public JsonResult UploadFileChunks()
        {
            var files = Request.Form.Files;

            if (files.Count > 0)
            {
                try
                {
                    var file = files.First();
                    string filePath = Path.Combine(GetUploadPath(), file.FileName);
                    using (var ms = new MemoryStream())
                    {
                        file.CopyTo(ms);
                        var fileBytes = ms.ToArray();

                        using (FileStream fs = new FileStream(filePath, FileMode.Append))
                        {
                            var bytes = fileBytes;
                            fs.Write(bytes, 0, bytes.Length);
                        }
                    }

                    return Json(new { status = true });
                }
                catch (Exception ex)
                {
                    return Json(new { status = false, message = ex.Message });
                }
            }

            return Json(new { status = false });
        }

        private string GetUploadPath()
        {
            string rootPath = Path.Combine(_env.WebRootPath, "UploadedFiles");

            if (!Directory.Exists(rootPath))
            {
                Directory.CreateDirectory(rootPath);
            }

            return rootPath;
        }
    }
}

參考資料:https://www.dotnetbull.com/2018/09/uploading-large-file-chunks-javascript-ajax-mvc-dotnet.html