Search code examples
c#azure-functionsmultipartform-datamultipartazure-function-app

Multipart Data Upload - Azure Function V2


Am uploading a document to HTTP Trigger Azure function(Version 2). On receiving the request in my function I see the Files section empty and stream is moved to formdata dictionary. Below is the code how am uploading the document, could someone help me why its not populating the stream in IFormFileCollection.


      using (var _httpClient = new HttpClient())
            {
                MultipartFormDataContent form = new MultipartFormDataContent();
                String headerValue = "form-data; name=\"file\"; filename=\"" + fileName + "\"";
                byte[] bytes = Encoding.UTF8.GetBytes(headerValue);
                headerValue = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                fileContent.Headers.Add("Content-Disposition", headerValue);
                fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
                form.Add(fileContent);
                form.Add(new StringContent(metadataValue), metadataKey);
                _httpClient.Timeout = TimeSpan.FromMinutes(15);
                _httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + bearerToken);
                logger.LogInformation($"HttpUtils: UploadFileByMultipart() url:{url}, request param: {metadataValue} reference: {traceLogId}");
                var response = await _httpClient.PostAsync(url, form).Result.Content.ReadAsStringAsync();
                logger.LogInformation("HttpUtils: UploadFileByMultipart() end");
                return response;
            }

Content received in Function

Other note how do take the stream from the Formdata dictionary which is in string format and convert to stream which I can play around. I tried below and the resultant is a blank doc, corrupting all the stream

        requestHandler.stream = new MemoryStream();
        var Content = formdata["file"].ToString();
        var fileContent = new MemoryStream(Encoding.ASCII.GetBytes(Content));

Solution

  • If we want to send Multipart Data with HttpClient, you can use MultipartFormDataContent to create data.

    For example

    The code I send request

    MultipartFormDataContent form = new MultipartFormDataContent();
    
                form.Add(new StringContent("jack"), "userName");
    
                var fileContent = new ByteArrayContent(File.ReadAllBytes(@"D:\my.csv"));
    
                // I use package MimeMapping : https://www.nuget.org/packages/MimeMapping/ to get file mine type
                fileContent.Headers.ContentType = new MediaTypeHeaderValue(MimeUtility.GetMimeMapping("my.csv"));
                fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                {
                    Name = "file",
                    FileName = "my.csv"
                };
                form.Add(fileContent);
    
                using (var client = new HttpClient())
                {
                    var res = await client.PostAsync("<function app url>", form);
                    if (res.IsSuccessStatusCode)
                    {
                        var content = await res.Content.ReadAsStringAsync();
                        Console.WriteLine(content);
    
                    }
    
                }
    
    1. My function app code
    using System.Net;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Newtonsoft.Json;
    
    public static async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
      ILogger log)
    {
                log.LogInformation("C# HTTP trigger function processed a request.");
    
                log.LogInformation("-------------------read file----------------------");
                // read file
                var files = req.Form.Files;
                if (files.Count != 0) {
                    var file = files[0];
                    
                    log.LogInformation(file.ContentType);
                    log.LogInformation(file.FileName);
                    log.LogInformation(file.ContentDisposition);
                    // use file.OpenReadStream to get a stream then use stream to rread file content
    
                }
    
                // read key
    
                log.LogInformation("-------------------read key----------------------");
                log.LogInformation($"The userName is {req.Form["userName"]}");
    
                return new OkObjectResult("OK");
    }
    

    enter image description here