1

I have a problem with the application sending the file to the web service. This is my endpoint/controller.

[HttpPost]
    public async Task<IActionResult> Post(List<IFormFile> files)
    {
       
        long size = files.Sum(f => f.Length);

        foreach (var formFile in files)
        {
            if (formFile.Length > 0)
            {
                var filePath = "C:\\Files\\TEST.pdf";

                using (var stream = System.IO.File.Create(filePath))
                {
                    await formFile.CopyToAsync(stream);
                }
            }
        }

This controller works fine in Postman.

and this is my application that makes the request:

             byte[] bytes = System.IO.File.ReadAllBytes("C:\\Files\\files.pdf");

             Stream fileStream = File.OpenRead("C:\\Files\\files.pdf");

             HttpContent bytesContent = new ByteArrayContent(bytes);
            
             using (var client = new HttpClient())
             using (var formData = new MultipartFormDataContent())
             {
                 formData.Add(bytesContent,"file", "files.pdf");
                 try
                 {
                     var response = await client.PostAsync(url, formData);
                 }catch(Exception ex)
                 {
                     Console.WriteLine(ex);
                 }

It doesn't work. I'm not receiving the file in controller. I also tried this:

            string fileToUpload = "C:\\Files\\files.pdf";
            using (var client = new WebClient())
            {
                byte[] result = client.UploadFile(url, fileToUpload);
                string responseAsString = Encoding.Default.GetString(result);
            }

but the result is the same. Would you be able to help?

Sebastian
  • 33
  • 5
  • Do you have the logs available for us? – frankfurt-laravel Sep 14 '20 at 10:53
  • When calling the request "var response = await client.PostAsync (url, formData)" the program terminates, or calls the request which I receive in the controller but the ,,List files" is null". It does not throw any exception. Looks like he's not sending the file. I don't know how to find out otherwise – Sebastian Sep 14 '20 at 11:01
  • When you are using HttpClient I bet you should also add some headers to request that will tell server that you are sending file. Check this answer https://stackoverflow.com/questions/42212406/how-to-send-a-file-and-form-data-with-httpclient-in-c-sharp/42212590 – DespeiL Sep 14 '20 at 11:10
  • For version with httpclient, the request is sent and not received by the controller. I do not know why – Sebastian Sep 14 '20 at 11:48

1 Answers1

1

Update 15/09/2020

This is the upload codes in ConsoleApplication. And it works with small file but not large file.

    public static async Task upload(string url)
    {

        //const string url = "https://localhost:44308/file/post";
        const string filePath = "C:\\Files\\files.pdf";

        try { 
            using (var httpClient = new HttpClient{
                Timeout = TimeSpan.FromSeconds(3600)
            })
            {
                using (var form = new MultipartFormDataContent())
                {
                    using (var fs = System.IO.File.OpenRead(filePath))
                    {
                        fs.Position = 0;
                        using (var streamContent = new StreamContent(fs))
                        {
                            
                            form.Add(streamContent, "files", Path.GetFileName(filePath));
                            HttpResponseMessage response = httpClient.PostAsync(url, form).Result;
                            fs.Close();

                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

    }




There are two steps to fix your problem.

1.Add ContentType to Headers

bytesContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

2. The file parameter name in formData should match action parameter name.

formData.Add(bytesContent,"file", "files.pdf"); //should be files


public async Task<IActionResult> Post(List<IFormFile> files)

Update

HttpClient.PostAsync() doesn't work when awaited in Console Application. Instead of blocking with .Result, use .GetAwaiter().GetResult().

HttpResponseMessage response = httpClient.PostAsync(url, form).Result;


Here is the code to show how to upload file.

Codes of Controller

public class FileController : Controller
    {
        [HttpPost]
        public async Task<IActionResult> Post(List<IFormFile> files)
        {

            long size = files.Sum(f => f.Length);

            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    var filePath = "C:\\Files\\TEST.pdf";

                    using (var stream = System.IO.File.Create(filePath))
                    {
                        await formFile.CopyToAsync(stream);
                    }
                }
            }

            return Ok();
        }

        [HttpGet]
        public async Task<IActionResult> upload()
        {

            const string url = "https://localhost:44308/file/post";
            const string filePath = @"C:\\Files\\files.pdf";

            using (var httpClient = new HttpClient())
            {
                using (var form = new MultipartFormDataContent())
                {
                    using (var fs = System.IO.File.OpenRead(filePath))
                    {
                        using (var streamContent = new StreamContent(fs))
                        {
                            using (var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync()))
                            {
                                fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

                                // "file" parameter name should be the same as the server side input parameter name
                                form.Add(fileContent, "files", Path.GetFileName(filePath));
                                HttpResponseMessage response = await httpClient.PostAsync(url, form);
                            }
                        }
                    }
                }
            }

            return Ok();

        }
    }

Test

enter image description here

Michael Wang
  • 3,782
  • 1
  • 5
  • 15
  • Thank you for your answer!! I have one question. Because I am creating, a console application that uploads the file to the web service. On line ,,var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync()" the application ends and does not continue. The application does not throw exceptions. Why is this happening? – Sebastian Sep 14 '20 at 13:33
  • 1
    @Sebastian , `HttpClient.PostAsync()` doesn't work when awaited in Console Application. Try `HttpResponseMessage response = httpClient.PostAsync(url, form).Result;`, and it works on my ConsoleApp. – Michael Wang Sep 14 '20 at 14:18
  • I want to accept the answer because it's great, but I'm having trouble with filestream. I have error ReadTimeout = 'file.ReadTimeout' threw an exception of type 'System.InvalidOperationException' WriteTimeout = 'file.WriteTimeout' threw an exception of type 'System.InvalidOperationException'. I don't know how to fix it in console application. It works great on the web service. – Sebastian Sep 15 '20 at 08:23
  • 1
    @Sebastian, I found that your issue is related with the size of file. I haven't deal with that and will keep on working it. – Michael Wang Sep 15 '20 at 11:47
  • @Micheal Thank you! I deal with it. In postman I use C# RestSharp. Copy and paste, and everthing is all right – Sebastian Sep 15 '20 at 12:04