5

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);
    }
halfer
  • 19,824
  • 17
  • 99
  • 186
Terje Nygård
  • 1,233
  • 6
  • 25
  • 48
  • 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 – Sameer Singh Jul 18 '14 at 09:08
  • 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 Jul 18 '14 at 09:12
  • 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 ? – Terje Nygård Jul 18 '14 at 09:13
  • 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](http://stackoverflow.com/questions/17072767/web-api-how-to-access-multipart-form-values-when-using-multipartmemorystreampro/17073113#17073113). – Sameer Singh Jul 18 '14 at 09:21
  • There's also [this](http://stackoverflow.com/a/15843410/501556) from the same developer. – Sameer Singh Jul 18 '14 at 09:23
  • 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 Jul 18 '14 at 09:38

2 Answers2

3

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.

Community
  • 1
  • 1
Sameer Singh
  • 1,358
  • 1
  • 19
  • 47
  • 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 :) – Terje Nygård Jul 22 '14 at 13:25
  • Currently, it's in `System.Net.Formatting.dll` within the [Microsoft.AspNet.WebApi.Client](https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Client/) NuGet package. Here's the [latest source code](http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Net.Http.Formatting/MultipartStreamProvider.cs) (it hasn't been changed in almost a year). – Sameer Singh Jul 22 '14 at 13:48
  • Yess !!.. it's working :) only annoying thing now is that i cannot get the rest of the formdata :( used this before ----> private object GetFormData(MultipartFormDataStreamProvider result) { if (result.FormData.HasKeys()) { var unescapedFormData = Uri.UnescapeDataString(result.FormData .GetValues(0).FirstOrDefault() ?? String.Empty); if (!String.IsNullOrEmpty(unescapedFormData)) return JsonConvert.DeserializeObject(unescapedFormData); } return null; } – Terje Nygård Jul 22 '14 at 14:57
  • guess that was your issue too ? ;) – Terje Nygård Jul 22 '14 at 14:57
  • My issue was just trying to stop the auto-magical file saving. I probably missed something, but [here's a gist of my attempt](https://gist.github.com/TheSamsterSA/ce52dd8ed45cec9be0c1); it might help point you in the right direction. – Sameer Singh Jul 22 '14 at 16:23
3

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.

Abhay Garg
  • 139
  • 7