0

In my xamarin.forms app. I am using Media.plugin to select images from gallery and camera.And also file picker plugin to select files like pdf,jpg etc from file manager.User can select multiple images and files and It will store in an observable collection.In this observable collection I have the path of images as well as files. Where I am stuck is I want to send these data to rest API by using multipart/form data.How can I send these multiple files to the server? Any help is appreciated.

My ObservableCollection

  public ObservableCollection<SelectedDocumentModel> DataManager
        {
            get
            {
                return _selectedfile ?? (_selectedfile = new ObservableCollection<SelectedDocumentModel>());
            }
        }

My Data Model

   public class SelectedDocumentModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }



        public string FileName { get; set; }
        public string Path { get; set; }
        public ImageSource SelectedImage { get; set; }
        public object Tasks { get; internal set; }

        private bool isLoadingVisible = false;
        public bool IsLoadingVisible
        {

            get
            {
                return isLoadingVisible;
            }

            set
            {
                if (value != null)
                {
                    isLoadingVisible = value;
                    NotifyPropertyChanged("IsLoadingVisible");
                }
            }
        }     
    }

Selecting image using media.plugin and allocating to my observable collection

 var Filename = Path.GetFileName(file.Path);
                            var FilePath = file.Path;
                            var newList = new SelectedDocumentModel()
                            {
                                FileName = Filename,
                                SelectedImage = imageSource,
                                IsLoadingVisible = false,
                                Path = FilePath
                            };
                            DataManager.Add(newList);

Selecting file from file manager using filepicker plugin and assign to observablecollection

var FilePath = pickedFile.FilePath;
                                var newList = new SelectedDocumentModel()
                                {
                                    FileName = filename,
                                    SelectedImage = imageSource,
                                    IsLoadingVisible = false,
                                    Path= FilePath
                                };
                                DataManager.Add(newList);

EDIT

This is what I should do using httpclient.Currently these are written using RestSharp.

var client = new RestClient("{{api_url}}/MYData");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "bearer {{token}}");
request.AddHeader("Content-Type", "application/json");
request.AlwaysMultipartFormData = true;
request.AddParameter("ids", " [{\"id\":1,\"person_id\":5}]");
request.AddParameter("title", " Test");
request.AddParameter("description", " Test");
request.AddParameter("send_text_message", " true");
request.AddParameter("text_message", " Test");
request.AddParameter("notification_type"," global");
request.AddParameter("my_files", "[
  { 
  \"name\": \"abc.jpg\",
  \"key\": \"1583307983694\"
}
]");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

What I have done by the way suggested by Lucas Zhang - MSFT.

try {
                MultipartFormDataContent multiContent = new MultipartFormDataContent();
                foreach (SelectedDocumentModel model in SelectedFileData)
                {
                    byte[] byteArray = Encoding.UTF8.GetBytes(model.Path);
                    MemoryStream stream = new MemoryStream(byteArray);
                    HttpContent fileStreamContent1 = new StreamContent(stream);
                    fileStreamContent1.Headers.ContentDisposition = new
                    System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
                    {
                        Name = model.FileName,
                        FileName = model.FileName
                    };
                    fileStreamContent1.Headers.ContentType = new
                    System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
                    multiContent.Add(fileStreamContent1);
                }

                multiContent.Add(new StringContent(notificationdetails[0]), "title");
                multiContent.Add(new StringContent(notificationdetails[1]), "description");
                multiContent.Add(new StringContent(notificationdetails[3]), "type");
                multiContent.Add(new StringContent(notificationdetails[7]), "send_text_message");
                multiContent.Add(new StringContent(notificationdetails[2]), "text_message");
                multiContent.Add(new StringContent(notificationdetails[8]), "send_email");
                multiContent.Add(new StringContent(notificationdetails[9]), "notification_type");

                HttpClient client = new HttpClient();
                client.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue("bearer",Settings.AuthToken);          
                var response = await client.PostAsync(url, multiContent);
                var responsestr = response.Content.ReadAsStringAsync().Result;
                await DisplayAlert("Result", responsestr.ToString(), "ok");


            }
            catch (Exception ex)
            {
                await DisplayAlert("Result", ex.Message.ToString(), "ok");
            }

unfortunately it not working.It not sending the data as I intend.

How can I upload each files as multipart/formdata on a button click.?Any help is appriciated.

Anand
  • 1,866
  • 3
  • 26
  • 49

1 Answers1

4

You could use MultipartFormDataContent to add multiple images,and use ContentDispositionHeaderValue.Parameters to add the values of your Data.

Usage

var fileStream = pickedFile.GetStream();
var newList = new SelectedDocumentModel()
                                {
                                    FileName = filename,
                                    SelectedImage = imageSource,
                                    IsLoadingVisible = false,
                                    Path= FilePath,
                                    Data = fileStream ,
                                };

MultipartFormDataContent multiContent = new MultipartFormDataContent();


foreach(var SelectedDocumentModel model in DataManager)
{
  HttpContent fileStreamContent1 = new StreamContent(model.Data);
  fileStreamContent1.Headers.ContentDisposition = new 
  System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") 
  {
     Name = "File", 
     FileName = "xxx.jpg" 
  };
  fileStreamContent1.Headers.ContentType = new 
  System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
  multiContent.Add(fileStreamContent1);


  multiContent.Add(new StringContent(model.Title), "model.Title");
  multiContent.Add(new StringContent(model.Description), "model.Description");
  multiContent.Add(new StringContent(model.Detail), "model.Detail");  
}

// Send (url = url of api) ,use httpclient
var response = await client.PostAsync(url, multiContent);

Community
  • 1
  • 1
Lucas Zhang
  • 18,630
  • 3
  • 12
  • 22
  • Is it possible to upload these without pluign? Because I have some other values need to be pass along with this api request like some title, description. and some ids etc.. – Anand Mar 13 '20 at 05:27
  • Don't forget to accept the answer if it helps you :) – Lucas Zhang Mar 13 '20 at 07:54
  • hi bro sorry for not responding back. I am getting error at fileStreamContent1. It says it is null – Anand Mar 15 '20 at 10:52
  • Or you could upload them in a loop . – Lucas Zhang Mar 16 '20 at 01:35
  • Bro. In my edited question, I would like send just like the restsharp code by using Httpclient. What should be the changes I do? – Anand Mar 16 '20 at 04:56
  • Hey lucas could you help me – Anand Mar 16 '20 at 06:29
  • Bro it not solved the issue. I asked a seperate question. Can you look at it? https://stackoverflow.com/questions/60716703/xamarin-forms-upload-multiple-images-using-multipart-form-data-issue – Anand Mar 17 '20 at 05:35
  • Check https://stackoverflow.com/questions/59209643/xamarin-forms-upload-multiple-images-with-data – Lucas Zhang Mar 17 '20 at 05:41
  • I checked that. But in that answer they send the image individually. Can you please look at it https://stackoverflow.com/questions/60716703/xamarin-forms-upload-multiple-images-using-multipart-form-data-issue. I tried as you suggest.But still no luck – Anand Mar 17 '20 at 09:04
  • Bro. This answer helped me. A little problem , how can I get the list of the image and file from filestream1 to request.AddParameter("my_files", "[ { \"name\": \"abc.jpg\", \"key\": \"1583307983694\" } ]"); this form? – Anand Mar 17 '20 at 12:10
  • `var fileStream = pickedFile.GetStream();` – Lucas Zhang Mar 18 '20 at 01:03