簡體   English   中英

無法從 URL Xamarin Form 下載圖像

[英]Unable to download Image from URL Xamarin Form

我正在開發一個 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");
    }
}

但它不起作用,沒有發現錯誤,我收到警報,警告我下載已完成。 我還允許internetwrite_external_storageread_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");
}

原因

您的功能“觸發並忘記”下載,然后直接向您顯示“下載完成”彈出窗口。 原因是您以同步方式( DownloadDataAsync )調用異步函數......這就是為什么它會在一段時間后仍然出現在庫中而您仍然會彈出。

解決方案

您應該首先閱讀: https : //docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

然后作為起點,嘗試聲明您的事件處理程序 async 並在適當的地方使用 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 模式重構另一種方法,但我想這為您提供了一個很好的起點。

編輯:

關於您編輯的新方法,請嘗試使用DownloadDataTaskAsyncCopyToAsync方法以及 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 以相同的方式調用它。

快樂編碼!

圖像已正確下載,我可以在文件資源管理器中看到它。

我通過重新刷新圖庫解決了我的問題,保存圖像后使用此行,因此方法將是:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM