Eliza Maria Ответов: 1

Как загрузить изображение на сервер .NET через api в xamarin?


Привет!


Я пытаюсь загрузить изображение на сервер .net с помощью xamarin, но у меня есть проблема, по-видимому, на стороне клиента.Когда я пытаюсь опубликовать изображение с помощью Postman непосредственно на стороне сервера,все работает отлично, и изображение сохраняется в папке в wwwroot.Однако,когда я выбираю изображение на стороне клиента,я получаю эту ошибку "
System.NullReferenceException: Object reference not set to an instance of an object.

Я использую "пример.Плагин.Media" nuget, который принимает изображение в качестве медиафайла, и я преобразую его в байты, чтобы он хранился в базе данных, так как в модели он объявлен как байтовый массив.Я попытался сделать метод api в веб-сервисе,чтобы взять изображение в качестве медиафайла, но по какой-то причине он выдает ошибку, о которой я упоминал выше.Я предполагаю,что поскольку серверная сторона имеет изображение как IFormFile, и я пытаюсь отправить его как MediaFile, он объявит его как нулевой объект.
Это мой класс моделей:
public  class User
   {
       public int IdUser { get; set; }
       public string Name { get; set; }
       public string Email { get; set; }
       public string Password { get; set; }
       public string ConfPassword { get; set; }
       public DateTime Created { get; set; } = DateTime.Now;
       public DateTime? Dob { get; set; }
       public byte[] Picture { get; set; }

       public virtual ICollection<Login> Login { get; set; }
   }


Метод api на стороне клиента:
public void UploadPicture(MediaFile image,string fileName)
        {
         <pre>  HttpContent fileStreamContent = new StreamContent(image.GetStream());
            fileStreamContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") { Name = "file", FileName = fileName };
            fileStreamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
            HttpClientHandler clientHandler = new HttpClientHandler();
            clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
            using (var client = new HttpClient(clientHandler))
            using (var formData = new MultipartFormDataContent())
            {
                formData.Add(fileStreamContent);
                var response = await client.PostAsync(pictureUrl, formData);
                if(response.IsSuccessStatusCode)
                {
                    //
                }
            }

}

Метод команды ViewModel для получения изображения и преобразования его в байтовый массив:
async Task UploadImage()
        {
          await CrossMedia.Current.Initialize();
        // await CrossPermissions.Current.RequestPermissionAsync<CameraPermission>();
            var mediaOptions = new PickMediaOptions()
            {
                PhotoSize = PhotoSize.Medium
            };
            var selectedImageFile = await CrossMedia.Current.PickPhotoAsync(mediaOptions);
            using (var memoryStream = new MemoryStream())
            {
                selectedImageFile.GetStream().CopyTo(memoryStream);
                Picture = memoryStream.ToArray();
               await service.UploadPictureAsync(selectedImageFile,selectedImageFile.ToString());
            }
            if (selectedImageFile == null)

            {
                await Application.Current.MainPage.DisplayAlert("Error", "Could not get file", "ok");
                return;
            }
           
        }


Серверный метод, который работает:
[HttpPost]
        public async Task Post(IFormFile file)
        {
            if (string.IsNullOrWhiteSpace(_environment.WebRootPath))
            {
                _environment.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
            }

            var uploads = Path.Combine(_environment.WebRootPath, "uploads");

            if (!Directory.Exists(uploads)) Directory.CreateDirectory(uploads);

            if (file.Length > 0)
            {
                using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
                {
                    await file.CopyToAsync(fileStream);
                }
            }
        }


Есть ли какое-либо обходное решение, которое позволит мне преобразовать медиафайл в IFormFile для отправки его на сервер или как я должен подойти к этому?Любая помощь будет оценена по достоинству!

Что я уже пробовал:

Я попытался настроить метод api для получения медиафайла следующим образом:
 public void UploadPicture(MediaFile image)
        {
           string pictureUrl = "http://10.0.2.2:5000/api/UploadPicture";
<pre> try
            {
                StreamContent content = new StreamContent(image.GetStream());
                content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                {
                    FileName = "newimage",
                    Name = "image"
                };
                content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
                HttpClientHandler clientHandler = new HttpClientHandler();
                clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
                var client = new HttpClient(clientHandler);
                var multi = new MultipartFormDataContent();
                multi.Add(content);
             
                var result = client.PostAsync(pictureUrl, multi).Result;
            
            }
            catch (Exception e)
            {
              
            }

Поскольку это мой первый раз,когда я работаю с загрузкой файлов, я взял этот метод с форума xamarin, он написан не мной.

1 Ответов

Рейтинг:
5

Sandeep Mewara

Ссылка на объект не установлена на экземпляр объекта
 
Эта ошибка возникает при попытке использовать свойство или вызвать метод объекта, который имеет значение null. Новые подробности: здесь[^]
 
Простое использование отладчика Visual studio может подсказать вам объект, из - за которого это происходит. Просто посмотрите на трассировку стека и поместите отладчик на эту линию. Проверьте объекты этой строки и посмотрите, является ли какой-либо из них нулевым, и вы пытаетесь использовать это свойство объектов. Справляйся с тем же.


Eliza Maria

Спасибо за ваш ответ, Сандип. Похоже, что он получает изображение, так что это не нулевое значение, но он возвращает ошибку "500 Bad request"

Sandeep Mewara

Так что вы знаете, где все идет не так. Теперь две вещи:
1. Ручки такие дела, которые не приводят к руде. Ваш код должен обрабатывать такой плохой ответ.
2. Найдите, почему вы получаете ошибку 500 и получите ее разрешение.

Eliza Maria

Итак,после того, как я немного исследовал, мне удалось найти что-то, что возвращает код состояния 200 ok.Однако у меня есть 2 вещи, которые я не могу понять:
1.хотя он возвращает "ОК",файл не сохраняется в папке на стороне сервера.
2.As я изменил метод, чтобы взять другой параметр с именем "fileName", я не уверен, как использовать его в виртуальной машине, чтобы на самом деле получить имя образа.

Я обновил вопрос с помощью нового кода, который у меня есть прямо сейчас для UploadPictureAsync() и UploadImage().Еще раз спасибо Вам за вашу помощь в выяснении того, как решить эту проблему :)

Sandeep Mewara

Поскольку вы сейчас пробуете новые вещи, я бы предложил вместо того, чтобы обновлять один и тот же вопрос, начать новый с ваших новых проблем для ясности.

Eliza Maria

ладно, Сандип,спасибо за помощь.Я сделаю это прямо сейчас.С наилучшими пожеланиями!