.NET Framework MVC Large file upload

Viewed 451

I am trying to upload large binary files from a web client to a .NET 4.6.1 Framework MVC API. These files could range anywhere from 5GB to 20GB.

I have tried splitting the file into chunks to upload each chunk and merge the results at the end, but the merged file is always corrupted. If I work with small files and don't split, the binary will work correctly. However, when I split and merge the file is "corrupted". It won't load or behave as expected.

I have looked all over and haven't seen a proper solution to this so i'm hoping someone can help me here.

I followed this https://forums.asp.net/t/1742612.aspx?How+to+upload+a+big+file+in+Mvc, but I can't get it to work and the corrected solution was never posted. I am keeping track of the order of files before merging on the server.

Javascript (Call to uploadData is made to initiate)

       function uploadComplete(file) {
            var formData = new FormData();
            formData.append('fileName', file.name);
            formData.append('completed', true);

            var xhr3 = new XMLHttpRequest();
            xhr3.open("POST", "api/CompleteUpload", true); //combine the chunks together
            xhr3.send(formData);

            return;
        }

        function uploadData(item) {           
            var blob = item.zipFile;
            var BYTES_PER_CHUNK = 750000000; // sample chunk sizes.
            var SIZE = blob.size;

            //upload content
            var start = 0;
            var end = BYTES_PER_CHUNK;
            var completed = 0;
            var count = SIZE % BYTES_PER_CHUNK == 0 ? SIZE / BYTES_PER_CHUNK : Math.floor(SIZE / BYTES_PER_CHUNK) + 1;

            while (start < SIZE) {
                var chunk = blob.slice(start, end);
                var xhr = new XMLHttpRequest();
                xhr.onload = function () {
                    completed = completed + 1;
                    if (completed === count) {
                        uploadComplete(item.zipFile);
                    }
                };
                xhr.open("POST", "/api/MultiUpload", true);
                xhr.setRequestHeader("contentType", false);
                xhr.setRequestHeader("processData", false);
                xhr.send(chunk);

                start = end;
                end = start + BYTES_PER_CHUNK;
            }
        } 

Server Controller

    //global vars
    public static List<string> myList = new List<string>();

    [HttpPost]
    [Route("CompleteUpload")]
    public string CompleteUpload()
    {
        var request = HttpContext.Current.Request;

        //verify all parameters were defined

        var form = request.Form;

        string fileName;
        bool completed;
        if (!string.IsNullOrEmpty(request.Form["fileName"]) &&
            !string.IsNullOrEmpty(request.Form["completed"]))
        {
            fileName = request.Form["fileName"];
            completed = bool.Parse(request.Form["completed"]);
        }
        else
        {
            return "Invalid upload request";
        }

        if (completed)
        {
            string path = HttpContext.Current.Server.MapPath("~/Data/uploads/Tamp");
            string newpath = Path.Combine(path, fileName);
            string[] filePaths = Directory.GetFiles(path);

            foreach (string item in myList)
            {
                MergeFiles(newpath, item);
            }
        }

        //Remove all items from list after request is done
        myList.Clear();
        return "success";
    }

    private static void MergeFiles(string file1, string file2)
    {
        FileStream fs1 = null;
        FileStream fs2 = null;
        try
        {
            fs1 = System.IO.File.Open(file1, FileMode.Append);
            fs2 = System.IO.File.Open(file2, FileMode.Open);
            byte[] fs2Content = new byte[fs2.Length];
            fs2.Read(fs2Content, 0, (int)fs2.Length);
            fs1.Write(fs2Content, 0, (int)fs2.Length);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message + " : " + ex.StackTrace + " " + file2);
        }
        finally
        {
            if(fs1 != null) fs1.Close();
            if (fs2 != null)
            {
                fs2.Close();
                System.IO.File.Delete(file2);
            }
        }
    }

    [HttpPost]
    [Route("MultiUpload")]
    public string MultiUpload()
    {
        try
        {                
            var request = HttpContext.Current.Request;
            var chunks = request.InputStream;

            string path = HttpContext.Current.Server.MapPath("~/Data/uploads/Tamp");
            string fileName = Path.GetTempFileName();
            string newpath = Path.Combine(path, fileName);
            myList.Add(newpath);

            using (System.IO.FileStream fs = System.IO.File.Create(newpath))
            {
                byte[] bytes = new byte[77570];

                int bytesRead;
                while ((bytesRead = request.InputStream.Read(bytes, 0, bytes.Length)) > 0)
                {
                    fs.Write(bytes, 0, bytesRead);
                }
            }
            return "test";
        }
        catch (Exception exception)
        {
            return exception.Message;
        }
    }
0 Answers
Related