Xamarin.Forms: How to download an Image, save it locally and display it on screen?

可紊 提交于 2020-04-14 08:06:53

问题


I have an issue with opening JPG file in native application on Android. I'm using newest release of Xamarin Essentials, there is some functionality called Launcher. Here is my code

await Launcher.TryOpenAsync("file:///" + localPath);

My local path is file stored in Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);.

Whenever I try to open that file I am getting error:

file:////data/user/0/mypackagename/files/.local/share/Screenshot.jpg exposed beyond app through Intent.getData()

I found several solutions here on stackoverflow, but I don't want to use Intent because my application is designed to be cross-platform (I would like to avoid native platform coding if this possible).

Launcher throws error on iOS also:

canOpenURL: failed for URL: ** -- file:///" - error: "This app is not allowed to query for scheme file

What am I doing wrong here?


回答1:


Step 1: Download the Image

We can use HttpClient to download the image.

HttpClient.GetByteArrayAsync will retrieve the image data and save it in memory.

In DownloadImage below, we will retrieve the image as a byte[].

static class ImageService
{
    static readonly HttpClient _client = new HttpClient();

    public static Task<byte[]> DownloadImage(string imageUrl)
    {
        if (!imageUrl.Trim().StartsWith("https", StringComparison.OrdinalIgnoreCase))
            throw new Exception("iOS and Android Require Https");

        return _client.GetByteArrayAsync(imageUrl);
    }
}

Step 2 Save Image to Disk

Now that we've downloaded the image, we will save it to disk.

Xamarin.Essentials.Preferences allows us to save items to disk using key-value pairs. Since byte[] is just a pointer to memory, we'll have to first convert the byte[] to base64-string before we can save it to disk.

static class ImageService
{
    static readonly HttpClient _client = new HttpClient();

    public static Task<byte[]> DownloadImage(string imageUrl)
    {
        if (!imageUrl.Trim().StartsWith("https", StringComparison.OrdinalIgnoreCase))
            throw new Exception("iOS and Android Require Https");

        return _client.GetByteArrayAsync(imageUrl);
    }

    public static void SaveToDisk(string imageFileName, byte[] imageAsBase64String)
    {
        Xamarin.Essentials.Preferences.Set(imageFileName, Convert.ToBase64String(imageAsBase64String));
    }
}

Step 3 Retrieve the Image for Display

Now that we've downloaded the image and saved it to disk, we need to be able to retrieve the image from disk to display it on the screen.

GetFromDisk below retrieves the image from disk and converts it to Xamarin.Forms.ImageSource.

static class ImageService
{
    static readonly HttpClient _client = new HttpClient();

    public static Task<byte[]> DownloadImage(string imageUrl)
    {
        if (!imageUrl.Trim().StartsWith("https", StringComparison.OrdinalIgnoreCase))
            throw new Exception("iOS and Android Require Https");

        return _client.GetByteArrayAsync(imageUrl);
    }

    public static void SaveToDisk(string imageFileName, byte[] imageAsBase64String)
    {
        Xamarin.Essentials.Preferences.Set(imageFileName, Convert.ToBase64String(imageAsBase64String));
    }

    public static Xamarin.Forms.ImageSource GetFromDisk(string imageFileName)
    {
        var imageAsBase64String = Xamarin.Essentials.Preferences.Get(imageFileName, string.Empty);

        return ImageSource.FromStream(() => new MemoryStream(Convert.FromBase64String(imageAsBase64String)));
    }
}

Example: Using ImageService in a Xamarin.Forms.ContentPage

class App : Application
{
    public App() => MainPage = new MyPage();
}

class MyPage : ContentPage
{
    readonly Image _downloadedImage = new Image();

    public MyPage()
    {
        Content = _downloadedImage;
    }

    protected override  async void OnAppearing()
    {
        const string xamrainImageUrl = "https://cdn.dribbble.com/users/3701/screenshots/5557667/xamarin-studio-1_2x_4x.png"
        const string xamarinImageName = "XamarinLogo.png";

        var downloadedImage = await ImageService.DownloadImage(xamrainImageUrl);

        ImageService.SaveToDisk(xamarinImageName, downloadedImage);

        _downloadedImage.Source = ImageService.GetFromDisk(xamarinImageName);
    }
}



来源:https://stackoverflow.com/questions/59632849/xamarin-forms-how-to-download-an-image-save-it-locally-and-display-it-on-scree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!