How to upload file in chunks in ASP.NET using ng-Flow

后端 未结 2 1589
别那么骄傲
别那么骄傲 2021-02-04 12:41

I am trying to implement ng-flow https://github.com/flowjs/ng-flow for file upload. It upload files in chunk, I successfully set this on client but I am not sure ho

相关标签:
2条回答
  • 2021-02-04 13:00

    Here's the ASP.NET Web API controller that I've come up with to save the chunks and assemble them.

    using System;
    using System.Diagnostics;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Net;
    using System.Net.Http;
    using System.IO;
    using System.Web;
    using System.Web.Http;
    
    namespace Api.Controllers
    {
        [RoutePrefix("api")]
        public class FlowUploadController : ApiController
        {
    
            string root = Path.Combine(Path.GetTempPath(), "FlowUpload");
    
            [Route("flowupload"), AcceptVerbs("GET")]
            public object Upload(
                int flowChunkNumber,
                string flowIdentifier)
            {
                if (ChunkIsHere(flowChunkNumber, flowIdentifier))
                {
                    return Request.CreateResponse(HttpStatusCode.OK);
                }
                else
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound);
                }
            }
    
            [Route("flowupload"), AcceptVerbs("POST")]
            public async Task<object> Upload()
            {
                // Check if the request contains multipart/form-data.
                if (!Request.Content.IsMimeMultipartContent())
                {
                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
                }
                if (!Directory.Exists(root)) Directory.CreateDirectory(root);
                var provider = new MultipartFormDataStreamProvider(root);
                try
                {
                    await Request.Content.ReadAsMultipartAsync(provider);
                    int chunkNumber = Convert.ToInt32(provider.FormData["flowChunkNumber"]);
                    int totalChunks = Convert.ToInt32(provider.FormData["flowTotalChunks"]);
                    string identifier = provider.FormData["flowIdentifier"];
                    string filename = provider.FormData["flowFilename"];
                    // Rename generated file
                    MultipartFileData chunk = provider.FileData[0]; // Only one file in multipart message
                    RenameChunk(chunk, chunkNumber, identifier);
                    // Assemble chunks into single file if they're all here
                    TryAssembleFile(identifier, totalChunks, filename);
                    // Success
                    return Request.CreateResponse(HttpStatusCode.OK);
                }
                catch (System.Exception e)
                {
                    return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
                }
    
            }
    
            private string GetChunkFileName(int chunkNumber, string identifier)
            {
                return Path.Combine(root, string.Format("{0}_{1}", identifier, chunkNumber.ToString()));
            }
    
            private void RenameChunk(MultipartFileData chunk, int chunkNumber, string identifier)
            {
                string generatedFileName = chunk.LocalFileName;
                string chunkFileName = GetChunkFileName(chunkNumber, identifier);
                if (File.Exists(chunkFileName)) File.Delete(chunkFileName);
                File.Move(generatedFileName, chunkFileName);
    
            }
    
            private string GetFileName(string identifier)
            {
                return Path.Combine(root, identifier);
            }
    
            private bool ChunkIsHere(int chunkNumber, string identifier)
            {
                string fileName = GetChunkFileName(chunkNumber, identifier);
                return File.Exists(fileName);
            }
    
            private bool AllChunksAreHere(string identifier, int totalChunks)
            {
                for (int chunkNumber = 1; chunkNumber <= totalChunks; chunkNumber++)
                    if (!ChunkIsHere(chunkNumber, identifier)) return false;
                return true;
            }
    
            private void TryAssembleFile(string identifier, int totalChunks, string filename)
            {
                if (AllChunksAreHere(identifier, totalChunks))
                {
                    // Create a single file
                    var consolidatedFileName = GetFileName(identifier);
                    using (var destStream = File.Create(consolidatedFileName, 15000))
                    {
                        for (int chunkNumber = 1; chunkNumber <= totalChunks; chunkNumber++)
                        {
                            var chunkFileName = GetChunkFileName(chunkNumber, identifier);
                            using (var sourceStream = File.OpenRead(chunkFileName))
                            {
                                sourceStream.CopyTo(destStream);
                            }
                        }
                        destStream.Close();
                    }
                    // Rename consolidated with original name of upload
                    filename = Path.GetFileName(filename); // Strip to filename if directory is specified (avoid cross-directory attack)
                    string realFileName = Path.Combine(root, filename);
                    if (File.Exists(filename)) File.Delete(realFileName);
                    File.Move(consolidatedFileName, realFileName);
                    // Delete chunk files
                    for (int chunkNumber = 1; chunkNumber <= totalChunks; chunkNumber++)
                    {
                        var chunkFileName = GetChunkFileName(chunkNumber, identifier);
                        File.Delete(chunkFileName);
                    }
                }
            }
    
        }
    }
    
    0 讨论(0)
  • 2021-02-04 13:03

    This repository on Github has implementation of parsing and consolidating of flow js chunks on MVC.

    It's very easy to implement. Just drop provided files in your project and your controller will look something like this

    -- Disclaimer. I'm the author of this repo.

    0 讨论(0)
提交回复
热议问题