Невозможно загрузить изображение с URL формы Xamarin - PullRequest
1 голос
/ 27 января 2020

Я занимаюсь разработкой приложения Xamarin, которое получает информацию из БД, делает / выбирает фотографию и загружает ее на удаленный сервер, отображает эти изображения с удаленного сервера, и пользователь может удалить их, нажав на и нажав кнопку. Последний шаг - загрузка изображений, хранящихся на сервере, в локальную галерею устройств.

Это мое текущее событие нажатия кнопки:

private void button_download_image_Clicked(object sender, EventArgs e)
{
        Uri image_url_format = new Uri(image_url);
        WebClient webClient = new WebClient();
        try
        {              
            webClient.DownloadDataAsync(image_url_format);
            webClient.DownloadDataCompleted += webClient_DownloadDataCompleted;
        }
        catch (Exception ex)
        {
            DisplayAlert("Error", ex.ToString(), "OK");
        }
}

Ниже метода webClient_DownloadDataCompleted:

private void webClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
    try
    {
        Uri image_url_format = new Uri(image_url);
        byte[] bytes_image = e.Result;
        Stream image_stream = new MemoryStream(bytes_image);
        string dest_folder= Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).ToString();
        string file_name= Path.GetFileName(image_url_format.LocalPath);
        string dest_path= Path.Combine(dest_folder, file_name);
        using (var fileStream = new FileStream(dest_path, FileMode.Create, FileAccess.Write))
        {
              image_stream.CopyTo(fileStream);
        }
              DisplayAlert("Alert", "Download completed!", "OK");
    }
    catch (Exception ex)
    {
        DisplayAlert("Error", ex.ToString(), "OK");
    }
}

Но это не работает, ошибки не обнаружены, я получаю предупреждение, которое предупреждает меня, что загрузка завершена. Также я дал разрешение на inte rnet, write_external_storage и read_external_storage .

Другое дело, что изображения через некоторое время появляются в галерея под Скачать альбом, который является правильным.

Есть идеи об этом поведении?

РЕДАКТИРОВАТЬ

Ниже моей новой кнопки событие загрузки:

private void button_download_image_Clicked(object sender, EventArgs e)
{

    Uri image_url_format = new Uri(image_url);
    WebClient webClient = new WebClient();
    try
    {
        byte[] bytes_image = webClient.DownloadData(image_url_format);
        Stream image_stream = new MemoryStream(bytes_image);
        string dest_folder = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).ToString();
        string file_name = Path.GetFileName(image_url_format.LocalPath);
        string dest_path = Path.Combine(dest_folder, file_name);
        using (var fileStream = new FileStream(dest_path, FileMode.Create, FileAccess.Write))
        {
            image_stream.CopyTo(fileStream);
        }
    }
    catch (Exception ex)
    {
        DisplayAlert("Error", ex.ToString(), "OK");
    }
    DisplayAlert("Alert", "File scaricato con successo", "OK");
}

Ответы [ 2 ]

0 голосов
/ 06 февраля 2020

Изображение было загружено правильно, и я вижу его в проводнике файлов.

Я решил свою проблему с помощью resfre sh галереи, с этими строками после сохранения моего изображения, поэтому метод будет быть:

private void button_download_image_Clicked(object sender, EventArgs e)
{
    Uri image_url_format = new Uri(image_url);
    WebClient webClient = new WebClient();
    try
    {
        byte[] bytes_image = webClient.DownloadData(image_url_format);
        Stream image_stream = new MemoryStream(bytes_image);
        string dest_folder = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).ToString();
        string file_name = Path.GetFileName(image_url_format.LocalPath);
        string dest_path = Path.Combine(dest_folder, file_name);
        using (var fileStream = new FileStream(dest_path, FileMode.Create, FileAccess.Write))
        {
            image_stream.CopyTo(fileStream);
        }
        // this 3 lines fix my problem
        var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
        mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(dest_path)));
        Android.App.Application.Context.SendBroadcast(mediaScanIntent);
    }
    catch (Exception ex)
    {
        DisplayAlert("Error", ex.ToString(), "OK");
    }
    DisplayAlert("Alert", "File scaricato con successo", "OK");
}
0 голосов
/ 27 января 2020

Причины

Ваша функция «запускает и забывает» о загрузке, а затем непосредственно показывает всплывающее окно «Загрузка завершена». Причина в том, что вы вызываете асинхронные функции синхронно (DownloadDataAsync) ... Вот почему это все равно будет отображаться через некоторое время в галерее, пока вы по-прежнему получаете всплывающее окно.

Решения

Сначала вы должны прочитать, что: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

Затем в качестве отправной точки попробуйте объявить обработчик событий. asyn c и используйте ключевое слово await в соответствующих местах:

private async void button_download_image_Clicked(object sender, EventArgs e)
{
    Uri image_url_format = new Uri(image_url);
    WebClient webClient = new WebClient();
    try
    {            
        await webClient.DownloadDataAsync(image_url_format); // This will await the download
        ...
    }
    catch (Exception ex)
    {
        ...
    }
}

Конечно, было бы лучше также провести рефакторинг другого метода, используя шаблон async / await, но это дает вам Хорошая отправная точка, я думаю.

РЕДАКТИРОВАТЬ:

Что касается нового метода, который вы отредактировали, попробуйте использовать методы DownloadDataTaskAsync и CopyToAsync вместе с шаблоном async / await:

 private async void  button_download_image_Clicked(object sender, EventArgs e)
    {

        Uri image_url_format = new Uri("url");
        WebClient webClient = new WebClient();
        try
        {
            byte[] bytes_image = await webClient.DownloadDataTaskAsync(image_url_format);
            Stream image_stream = new MemoryStream(bytes_image);
            string dest_folder = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).ToString();
            string file_name = Path.GetFileName(image_url_format.LocalPath);
            string dest_path = Path.Combine(dest_folder, file_name);
            using (var fileStream = new FileStream(dest_path, FileMode.Create, FileAccess.Write))
            {
                await image_stream.CopyToAsync(fileStream);
            }
        }
        catch (Exception ex)
        {
           await DisplayAlertAsync("Error", ex.ToString(), "OK");
        }
        await DisplayAlertAsync("Alert", "File scaricato con successo", "OK");
    }

Кроме того, вы должны создать метод DisplayAlertAsync и вызывать его так же, используя await.

Счастливого кодирования!

...