4

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.

terbubbs
  • 1,512
  • 2
  • 25
  • 48

2 Answers2

4

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;
}
terbubbs
  • 1,512
  • 2
  • 25
  • 48
1

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;
        }
Rolwin Crasta
  • 4,219
  • 3
  • 35
  • 45
  • Thank you for the response. The code I posted above does not occur in WebAPI. It is posting to WebAPI where the saving is done. I have no issue receiving multiple files; the issue lies in posting multiple files over. As you can see, I am able to create StreamContent containing a single file, but I would like it to contain multiple files if possible. – terbubbs Oct 16 '15 at 13:41
  • I have edited my answer to include Stream of each posted file. – Rolwin Crasta Oct 16 '15 at 13:43
  • Yes I noticed that. However, like I said in my previous comment, I do not have any issues receiving and saving the posted files. The issue lies in creating the StreamContent necessary to post multiple files. – terbubbs Oct 16 '15 at 13:44