terbubbs
terbubbs

Reputation: 1512

POST StreamContent with Multiple Files

The code snippet below successfully HttpPosts a single file to WebAPI. I'd like expand it to build StreamContent containing multiple files (similar to Fiddler multi-file posts).

I know I should be adding a "boundary" to the StreamContent, but I'm not sure exactly where. I'd like to eventually convert the FileStream/Stream parameters to be a List so I can iterate through the collection and build StreamContent to POST.

Let me know if this post makes any sense. I'd appreciate any suggestions.

Thanks in advance!

public async Task<HttpStatusCode> UploadOrderFile(FileStream imageFileStream, string filename, string contentType = "image/png")
    {
        JsonApiClient._client.DefaultRequestHeaders.Clear();
        var content = new MultipartFormDataContent
        {
            JsonApiClient.CreateFileContent(imageFileStream, filename, contentType)
        };
        JsonApiClient._client.DefaultRequestHeaders.Add("Authorization",
            " Bearer " + JsonApiClient.Token.AccessToken);
        var response = await JsonApiClient._client.PostAsync("api/UploadFile", content);

        response.EnsureSuccessStatusCode();
        return response.StatusCode;
    }

internal static StreamContent CreateFileContent(Stream stream, string fileName, string contentType)
    {
        var fileContent = new StreamContent(stream);
        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
        {
            Name = "\"files\"",
            FileName = "\"" + fileName + "\""
        }; 
        fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
        return fileContent;
    }

EDIT: I do not have any issues receiving and saving the posted files. The issue lies in creating the StreamContent necessary to post multiple files.

Upvotes: 4

Views: 5156

Answers (2)

terbubbs
terbubbs

Reputation: 1512

This is a solution that I tried that works for me. Nothing was changed in CreateFileContent. I just simply converted parameters into collections, iterated through each collection, and added new MultiPartFormDataContent out of multiple StreamContent. The boundary was also added to the MultipartFormDataContent object. If you see anything that is inefficient or plain wrong, let me know. Thanks!

public async Task<HttpStatusCode> UploadOrderFile(List<FileStream> imageFileStream, List<string> filename, string salesOrderNo, List<string> contentType)
    {
        JsonApiClient._client.DefaultRequestHeaders.Clear();
        var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
        var content = new MultipartFormDataContent(boundary); 
        for (var i = 0; i < imageFileStream.Count; i++)
        {
            content.Add(JsonApiClient.CreateFileContent(imageFileStream[i], filename[i], contentType[i]));
        }

        JsonApiClient._client.DefaultRequestHeaders.Add("Authorization",
            " Bearer " + JsonApiClient.Token.AccessToken);
        var response = await JsonApiClient._client.PostAsync("api/UploadFile", content);

        response.EnsureSuccessStatusCode();
        return response.StatusCode;
    }

internal static StreamContent CreateFileContent(Stream stream, string fileName, string contentType)
{
    var fileContent = new StreamContent(stream);
    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
    {
        Name = "\"files\"",
        FileName = "\"" + fileName + "\""
    }; 
    fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
    return fileContent;
}

Upvotes: 4

Rolwin Crasta
Rolwin Crasta

Reputation: 4339

Try this approach

     public HttpResponseMessage Post()
        {
            var httpRequest = HttpContext.Current.Request;
            if (httpRequest.Files.Count > 0)
            {
                foreach(string file in httpRequest.Files)
                {                   
 var content = new MultipartFormDataContent
        {
            JsonApiClient.CreateFileContent(postedFile.InputStream, postedFile.FileName, postedFile.ContentType)
        };
                 // NOTE: To store in memory use postedFile.InputStream
                }

                return Request.CreateResponse(HttpStatusCode.Created);
            }

            return Request.CreateResponse(HttpStatusCode.BadRequest);
        }


    internal static StreamContent CreateFileContent(Stream stream, string fileName, string contentType)
        {
            var fileContent = new StreamContent(stream);
            fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
            {
                Name = "\"files\"",
                FileName = "\"" + fileName + "\""
            }; 
            fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
            return fileContent;
        }

Upvotes: 1

Related Questions