How to get the stream for a Multipart file in webapi upload?

23,093

Solution 1

This is identical to a dilemma I had a few months ago (capturing the upload stream before the MultipartStreamProvider took over and auto-magically saved the stream to a file). The recommendation was to inherit that class and override the methods ... but that didn't work in my case. :( (I wanted the functionality of both the MultipartFileStreamProvider and MultipartFormDataStreamProvider rolled into one MultipartStreamProvider, without the autosave part).

This might help; here's one written by one of the Web API developers, and this from the same developer.

Solution 2

Hi just wanted to post my answer so if anybody encounters the same issue they can find a solution here itself.

here

 MultipartMemoryStreamProvider stream = await this.Request.Content.ReadAsMultipartAsync();
            foreach (var st in stream.Contents)
            {
                var fileBytes = await st.ReadAsByteArrayAsync();
                string base64 = Convert.ToBase64String(fileBytes);
                var contentHeader = st.Headers;
                string filename = contentHeader.ContentDisposition.FileName.Replace("\"", "");
                string filetype = contentHeader.ContentType.MediaType;
            }    

I used MultipartMemoryStreamProvider and got all the details like filename and filetype from the header of content. Hope this helps someone.

Share:
23,093
Terje Nygård
Author by

Terje Nygård

Updated on July 09, 2022

Comments

  • Terje Nygård
    Terje Nygård almost 2 years

    I need to upload a file using Stream (Azure Blobstorage), and just cannot find out how to get the stream from the object itself. See code below.

    I'm new to the WebAPI and have used some examples. I'm getting the files and filedata, but it's not correct type for my methods to upload it. Therefore, I need to get or convert it into a normal Stream, which seems a bit hard at the moment :)

    I know I need to use ReadAsStreamAsync().Result in some way, but it crashes in the foreach loop since I'm getting two provider.Contents (first one seems right, second one does not).

     [System.Web.Http.HttpPost]
        public async Task<HttpResponseMessage> Upload()
        {
            if (!Request.Content.IsMimeMultipartContent())
            {
                this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
            }
    
            var provider = GetMultipartProvider();
            var result = await Request.Content.ReadAsMultipartAsync(provider);
    
            // On upload, files are given a generic name like "BodyPart_26d6abe1-3ae1-416a-9429-b35f15e6e5d5"
            // so this is how you can get the original file name
            var originalFileName = GetDeserializedFileName(result.FileData.First());
    
            // uploadedFileInfo object will give you some additional stuff like file length,
            // creation time, directory name, a few filesystem methods etc..
            var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);
    
    
    
            // Remove this line as well as GetFormData method if you're not
            // sending any form data with your upload request
            var fileUploadObj = GetFormData<UploadDataModel>(result);
    
            Stream filestream = null;
    
            using (Stream stream = new MemoryStream())
            {
                foreach (HttpContent content in provider.Contents)
                {
                    BinaryFormatter bFormatter = new BinaryFormatter();
                    bFormatter.Serialize(stream, content.ReadAsStreamAsync().Result);
                    stream.Position = 0;
                    filestream = stream;
                }
            }
    
            var storage = new StorageServices();
            storage.UploadBlob(filestream, originalFileName);**strong text**
    
    
    
    private MultipartFormDataStreamProvider GetMultipartProvider()
        {
            var uploadFolder = "~/App_Data/Tmp/FileUploads"; // you could put this to web.config
            var root = HttpContext.Current.Server.MapPath(uploadFolder);
            Directory.CreateDirectory(root);
            return new MultipartFormDataStreamProvider(root);
        }
    
    • Sameer Singh
      Sameer Singh almost 10 years
      1. What does GetMultipartProvider() return? 2. I believe that you can get the file path of the auto-magically saved file from the provider and use the usual System.IO.File or System.IO.FileInfo classes to retrieve the stream
    • Terje Nygård
      Terje Nygård almost 10 years
      Here is the method :) private MultipartFormDataStreamProvider GetMultipartProvider() { var uploadFolder = "~/App_Data/Tmp/FileUploads"; // you could put this to web.config var root = HttpContext.Current.Server.MapPath(uploadFolder); Directory.CreateDirectory(root); return new MultipartFormDataStreamProvider(root); }
    • Terje Nygård
      Terje Nygård almost 10 years
      Can i get the file from here ? Basically i dont need to store it to disk.. i only need the stream for uploading to azure blob storage :) Any ideas ?
    • Sameer Singh
      Sameer Singh almost 10 years
      This is identical to a dilemma I had a few months ago (capturing the upload stream before the MultipartStreamProvider took over and auto-magically saved the stream to a file). The recommendation was to inherit that class and override the methods ... but that didn't work in my case. :( This might help; here's one written by one of the Web API developers.
    • Sameer Singh
      Sameer Singh almost 10 years
      There's also this from the same developer.
    • Terje Nygård
      Terje Nygård almost 10 years
      Thanks a bunch for this Sameer :) This will definately help me out big-time.. Just have to go through and understand this first :) hehe.. Kinda complex developing with web api for me at this beginner stage :) How can i accept your comment as an answer ?
  • Terje Nygård
    Terje Nygård almost 10 years
    Just one question about this :) how/where do i get and reference the multipartstreamprovider? Cannot find it in system.net.http. I have .net 4.5 :)
  • Sameer Singh
    Sameer Singh almost 10 years
    Currently, it's in System.Net.Formatting.dll within the Microsoft.AspNet.WebApi.Client NuGet package. Here's the latest source code (it hasn't been changed in almost a year).
  • Terje Nygård
    Terje Nygård almost 10 years
    Thanks for that Sameer ;)
  • Terje Nygård
    Terje Nygård almost 10 years
    Yess !!.. it's working :) only annoying thing now is that i cannot get the rest of the formdata :( used this before ----> private object GetFormData<T>(MultipartFormDataStreamProvider result) { if (result.FormData.HasKeys()) { var unescapedFormData = Uri.UnescapeDataString(result.FormData .GetValues(0).FirstOrDefault() ?? String.Empty); if (!String.IsNullOrEmpty(unescapedFormData)) return JsonConvert.DeserializeObject<T>(unescapedFormData); } return null; }
  • Terje Nygård
    Terje Nygård almost 10 years
    guess that was your issue too ? ;)
  • Sameer Singh
    Sameer Singh almost 10 years
    My issue was just trying to stop the auto-magical file saving. I probably missed something, but here's a gist of my attempt; it might help point you in the right direction.