Search code examples
c#wcf-web-api

Reading content to the memory from the multi-part file upload


I have a problem reading uploaded XML file to the string instead of file.

My problem is that when I try to access the stream (var stream = part.ContentReadStream) then it's closed. I have feeling that it is accessing closed file stream. Am I using MultipartFormDataStreamProvider incorrectly? File size is only few kilobytes, so that should not be a problem.

    [WebInvoke(Method = "POST", UriTemplate = "{importFile}")]
    public HttpResponseMessage Upload(string importFile, HttpRequestMessage request)
    {
        if (!request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        // Create a stream provider for setting up output streams
        MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider();

        // Read the MIME multipart content using the stream provider we just created.
        var task = request.Content.ReadAsMultipartAsync(streamProvider);
        task.Wait();
        IEnumerable<HttpContent> bodyparts = task.Result;
        string submitter;
        if (!bodyparts.TryGetFormFieldValue("submitter", out submitter))
        {
            submitter = "unknown";
        }

        // Get list of local file names from stream provider
        IDictionary<string, string> bodyPartFileNames = streamProvider.BodyPartFileNames;


        var parser = this.parserFactoryFactory.CreateParser();
        foreach (var part in bodyparts)
        {
            using (var stream = part.ContentReadStream)
            {
                using (var streamReader = new StreamReader(stream))
                {
                    string content = streamReader.ReadToEnd();
                    var results = parser.Parse(content);
                }
            }
        }
        return new HttpResponseMessage(HttpStatusCode.Accepted);
    }  

This is my post

<h3>Data import test</h3>

<form action="/api/data/Upload" enctype="multipart/form-data" method="POST">
    <input type="file" name="importFile"/>
    <input type="submit" value="Upload"/>
</form>

Solution

  • The solution was actually quite simple. MultipartFormDataStreamProvider is not required when we are not dealing with files. This works quite smoothly on my case.

    [WebInvoke(Method = "POST", UriTemplate = "{importFile}")]
    public HttpResponseMessage Upload(
        string importFile, HttpRequestMessage request)
    {
        if (!request.Content.IsMimeMultipartContent())
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    
        // Read the MIME multipart content 
        var task = request.Content.ReadAsMultipartAsync();            
        task.Wait();
    
        IEnumerable<HttpContent> bodyparts = task.Result;
        string submitter;
        if (!bodyparts.TryGetFormFieldValue("submitter", out submitter))
            submitter = "unknown";
    
        var parser = this.parserFactoryFactory.CreateParser();
        foreach (var part in bodyparts)
        {
            using (var stream = part.ContentReadStream)
            {
                using (var streamReader = new StreamReader(stream))
                {
                    string content = streamReader.ReadToEnd();
                    var results = parser.Parse(content);
                    if (results.IsValid)
                        // do something
                }
            }
        }
        var message = new HttpResponseMessage(HttpStatusCode.Accepted);
        return message;
    }