2

I am having a .pdf and .xml files which needs to be uploaded to an API at once (It means when I call an API, I need to upload these two files at the same time) from windows forms C# application.

Right now, I am looping in a for loop. So after uploading .pdf again in the loop it uploading .xml

Can anyone look into my code and tell me how can I upload two files in a single call?

    private void button1_Click(object sender, EventArgs e)
    {
        var openFileDialog = new OpenFileDialog();
        var dialogResult = openFileDialog1.ShowDialog();
        if (dialogResult != DialogResult.OK) return;
        string filecontent = "";
        using (StreamReader reader = new StreamReader(openFileDialog1.OpenFile()))
        {
            filecontent = reader.ReadToEnd();
        }
        string filename = openFileDialog1.FileName;
        string[] filenames = openFileDialog1.FileNames;
        for (int i = 0; i < filenames.Count(); i++)
        {
            UploadFilesAsync(filenames[i]);
        }
    }

    public static async Task<bool> UploadFilesAsync(params string[] paths)
    {
        HttpClient client = new HttpClient();

        var multiForm = new MultipartFormDataContent();

        foreach (string path in paths)
        {
            // add file and directly upload it
            FileStream fs = File.OpenRead(path);
            var streamContent = new StreamContent(fs);

            //string dd = MimeType(path);
            var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync());
            fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
            multiForm.Add(fileContent, "files", Path.GetFileName(path));
        }

        var url = "https://spaysaas-dev.smartdocs.ai/api/getOCRDocuments";
        using (var response = await client.PostAsync(url, multiForm))
        {
            return response.IsSuccessStatusCode;

            if(response.IsSuccessStatusCode)
            {
                MessageBox.Show("Suucessfully uploaded the file to Server");
            }
            else
            {
                MessageBox.Show("Issues in your code, Please Check...!!!");
            }
        }
    }
Venkat Sunil
  • 29
  • 1
  • 5

2 Answers2

3

add both files to the multiForm like this

static async Task<bool> UploadFilesAsync(params string[] paths)
{
    HttpClient client = new HttpClient();
    // we need to send a request with multipart/form-data
    var multiForm = new MultipartFormDataContent();

    foreach (string path in paths)
    {
        // add file and directly upload it
        FileStream fs = File.OpenRead(path);
        var streamContent = new StreamContent(fs);

        //string dd = MimeType(path);
        var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync());
        fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
        multiForm.Add(fileContent, "files", Path.GetFileName(path));
    }

    // send request to API
    var url = "http://localhost:5000/api/values/upload";
    using (var response = await client.PostAsync(url, multiForm))
    {
        return response.IsSuccessStatusCode;
    }
}

the http request will look something like this:

POST http://localhost:5000/api/values/upload HTTP/1.1
Content-Type: multipart/form-data; boundary="2fd255a5-5867-4d15-8b03-d7bdefdaeec3"
Content-Length: 1573
Host: localhost:5000

--2fd255a5-5867-4d15-8b03-d7bdefdaeec3
Content-Type: multipart/form-data
Content-Disposition: form-data; name=files; filename=page_word.png; filename*=utf-8''page_word.png

 PNG


IHDR           a   gAMA
....

--2fd255a5-5867-4d15-8b03-d7bdefdaeec3
Content-Type: multipart/form-data
Content-Disposition: form-data; name=files; filename=page_white_zip.png; filename*=utf-8''page_white_zip.png

 PNG


IHDR           7   
....

--2fd255a5-5867-4d15-8b03-d7bdefdaeec3--

addional explanations pointed out by @Jimi:

  • The multipart/form-data boundaries are randomly generated when you call the constructor of MultipartFormDataContet w/o arguments
  • streamContent.ReadAsByteArrayAsync().Result make the call synchronous and should be replaced by await streamContent.ReadAsByteArrayAsync()
  • PostAsync() should be wrapped by as using statement to dispose the request after it has completed
  • As for HttpClient: Decide for yourself how you wan't to handle it's lifecylcle since it is expensive to create an can be safly re-used (as discussed many times on SO, see Do HttpClient and HttpClientHandler have to be disposed?)
user1859022
  • 2,585
  • 1
  • 21
  • 33
  • 1
    You forgot to mention the `multipart/form-data`boundaries (the string separator's content and format, in `MultipartFormDataContent` or `Headers.ContentType`). You could also make the OP notice that nothing is disposed of in that code (especially the Stream(s)) and that `streamContent.ReadAsByteArrayAsync().Result` should really be `await streamContent.ReadAsByteArrayAsync()` – Jimi Aug 28 '19 at 13:12
  • @user1859022 Can you please show me, how can i add both files to the multiform. I am trying but no clue how to do that – Venkat Sunil Aug 28 '19 at 14:16
  • @user1859022 Actually, I have updated the code as you mentioned, but actually only one file is getting uploaded. Is there any mistakes I have done in the code. – Venkat Sunil Aug 29 '19 at 15:44
  • You are still **calling the method for each file**... Replace the `for` loop with `await UploadFilesAsync(filenames);` – user1859022 Aug 30 '19 at 06:19
  • @user1859022 Thank you for your support. I have completed my task – Venkat Sunil Aug 31 '19 at 18:02
  • @user1859022 Really Sorry, I forgot to accept your solution. Thank you very much for your support...!!! :) – Venkat Sunil Sep 03 '19 at 07:11
0
private async void BtnUploadInvoices_Click(object sender, EventArgs e)
    {
        string[] filenames = Directory.GetFiles("D:\\test")
                                 .Select(Path.GetFullPath)
                                 .ToArray();

        await UploadFileAsync(filenames);

        //Folder Creation
        if (!Directory.Exists(@"D:/" + "ProcessedFiles"))
            Directory.CreateDirectory(@"D:/" + "ProcessedFiles");


        if (Directory.Exists("D:\\test"))
        {
            foreach (var file in new DirectoryInfo("D:\\test").GetFiles())
            {
                if(file.Exists!=true)
                {
                    file.MoveTo($@"{"D:\\ProcessedFiles"}\{file.Name}");
                }
                else
                {
                    MessageBox.Show(file.Name + "already exists");
                }

            }
        }
    }

    public static async Task UploadFileAsync(string[] files)
    {
        if(files.Count()!=0)
        {
            HttpClient client = new HttpClient();
            // we need to send a request with multipart/form-data
            var multiForm = new MultipartFormDataContent();
            string fileMimeType = "";

            // add file and directly upload it
            for (int i = 0; i < files.Count(); i++)
            {
                FileStream fs = File.OpenRead(files[i]);
                var streamContent = new StreamContent(fs);
                if (Path.GetExtension(files[i]) == ".pdf")
                    fileMimeType = "application/pdf";
                else
                    fileMimeType = "application/xml";

                //string dd = MimeType(path);
                var imageContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
                imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse(fileMimeType);
                //imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
                multiForm.Add(imageContent, "files", Path.GetFileName(files[i]));
                fs.Close();
            }

            // send request to API
            var url = "https://localhost/api/getDocuments";
            var response = await client.PostAsync(url, multiForm);



            if (response.IsSuccessStatusCode)
            {
                MessageBox.Show("Success");
            }
            else
            {
                MessageBox.Show(response.ToString());
            }
        }
        else
        {
            MessageBox.Show("There are no files in the folder to process");
        }

    }
Venkat Sunil
  • 29
  • 1
  • 5