Anand
Anand

Reputation: 1959

xamarin.forms - Upload multiple images and files using multipart/form data

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.

Upvotes: 0

Views: 2190

Answers (1)

Lucas Zhang
Lucas Zhang

Reputation: 18861

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);

Upvotes: 4

Related Questions