Mochi
Mochi

Reputation: 1117

How to save an image in SQLite in Xamarin Forms?

I have the following two methods that handles taking photos from a camera and picking photos from a library. They're both similar methods as at the end of each method, I get an ImageSource back from the Stream and I pass it onto another page which has an ImageSource binding ready to be set. These two method work perfectly. The next step now is to save the Image in SQLite so I can show the images in a ListView later on. My question for the XamGods (Xamarin Pros =), what is the best way to save image in SQLite in 2019? I have been in the forums for hours and I still don't have a tunnel vision on what I want to do. I can either

I'm sorry if my question is general, but Xamarin does not provide a clear-cut solution on how to save images in SQLite and you can only find bits and pieces of solutions throughout the forums listed below.

Thank you in advance!

    private async Task OnAddPhotoFromCameraSelected()
    {
        Console.WriteLine("OnAddPhotoFromCameraSelected");

        var photo = await Plugin.Media.CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions() { });
        var stream = photo.GetStream();
        photo.Dispose();
        if (stream != null)
        {
            ImageSource cameraPhotoImage = ImageSource.FromStream(() => stream);
            var parms = new NavigationParameters();
            parms.Add("image", cameraPhotoImage);
            var result = await NavigationService.NavigateAsync("/AddInspectionPhotoPage?", parameters: parms);

            if (!result.Success)
            {
                throw result.Exception;
            }
        }
    }

    private async Task OnAddPhotoFromLibrarySelected()
    {
        Console.WriteLine("OnAddPhotoFromLibrarySelected");
        Stream stream = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();
        if (stream != null)
        {
            ImageSource selectedImage = ImageSource.FromStream(() => stream);

            var parms = new NavigationParameters();
            parms.Add("image", selectedImage);
            parms.Add("stream", stream);
            var result = await NavigationService.NavigateAsync("/AddInspectionPhotoPage?", parameters: parms);

            if (!result.Success)
            {
                throw result.Exception;
            }
        }
    }

Upvotes: 5

Views: 7755

Answers (1)

Cherry Bu - MSFT
Cherry Bu - MSFT

Reputation: 10346

As Jason said that you can save image path into sqlite database, but if you still want to save byte[] into sqlite database, you need to convert stream into byte[] firstly:

 private byte[] GetImageBytes(Stream stream)
    {
        byte[] ImageBytes;
        using (var memoryStream = new System.IO.MemoryStream())
        {              
            stream.CopyTo(memoryStream);             
            ImageBytes = memoryStream.ToArray();
        }
        return ImageBytes;
    }

Then load byte[] from sqlite, converting into stream.

 public Stream BytesToStream(byte[] bytes)
    {
        Stream stream = new MemoryStream(bytes);
        return stream;
    }

For simple sample, you can take a look: Insert byte[] in sqlite:

 private void insertdata()
    {
        var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "sqlite1.db3");
        using (var con = new SQLiteConnection(path))
        {
            Image image = new Image();
            image.Content = ConvertStreamtoByte();
            var result = con.Insert(image);

            sl.Children.Add(new Label() { Text = result > 0 ? "insert successful insert" : "fail insert" });
        }
    }

Loading image from sqlite:

 private void getdata()
    {
        var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "sqlite1.db3");
        using (var con = new SQLiteConnection(path))
        {
            var image= con.Query<Image>("SELECT content FROM Image ;").FirstOrDefault();

            if(image!=null)
            {
                byte[] b = image.Content;
                Stream ms = new MemoryStream(b);
                image1.Source = ImageSource.FromStream(() => ms);                   
            }

        }
    }

Model:

public class Image
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string FileName { get; set; }   
    public byte[] Content { get; set; }
}

Upvotes: 8

Related Questions