How to get the stream for a Multipart file in webapi upload?
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.
Terje Nygård
Updated on July 09, 2022Comments
-
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 almost 10 years1. 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 usualSystem.IO.File
orSystem.IO.FileInfo
classes to retrieve the stream -
Terje Nygård almost 10 yearsHere 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 almost 10 yearsCan 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 almost 10 yearsThis 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 almost 10 yearsThere's also this from the same developer.
-
Terje Nygård almost 10 yearsThanks 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 almost 10 yearsJust 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 almost 10 yearsCurrently, 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 almost 10 yearsThanks for that Sameer ;)
-
Terje Nygård almost 10 yearsYess !!.. 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 almost 10 yearsguess that was your issue too ? ;)
-
Sameer Singh almost 10 yearsMy 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.