1

in my app I would like to program an "offline version" of an display. That is, you can decide in advance to download the images and later videos and then view them without mobile data (due to network coverage), for example.

I use step 1 (Xamarin.Forms: How to download an Image, save it locally and display it on screen?) to download the file. Step 2 I can not use because the maximum data size is exceeded for larger files. So I use PCLStorage and save the file locally.

IFolder folder = FileSystem.Current.LocalStorage;
IFile file = await folder.CreateFileAsync(imageFileName, CreationCollisionOption.ReplaceExisting);
await file.WriteAllTextAsync(Convert.ToBase64String(imageAsBase64String));

Now I want to display the images again, but no matter what I do, the image is not shown. I rewrite the imagesource URL to the local file. No matter if only with "filename.jpg" or "file:///data/user/0/com.xxx.yyy_app/files/filename.jpg" no image is shown. But I can't even check if the image was downloaded correctly as such, because the files in localstorage are not shown in a filemanager. folder.CheckExistsAsync says that the file exists.

Partly I get this error:

  [0:] Image Loading: Error getting stream for file:///data/user/0/com.xxx.yyy_app/files/2_76_1.jpg: System.InvalidOperationException: 
An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.
  at System.Net.Http.HttpClient.PrepareRequestMessage (System.Net.Http.HttpRequestMessage request) [0x0008a] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpClient.cs:678 
  at System.Net.Http.HttpClient.SendAsync (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) [0x00020] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpClient.cs:437 
  at System.Net.Http.HttpClient.GetAsync (System.Uri requestUri, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpClient.cs:311 
  at System.Net.Http.HttpClient.GetAsync (System.Uri requestUri, System.Threading.CancellationToken cancellationToken) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpClient.cs:299 
  at Xamarin.Forms.StreamWrapper.GetStreamAsync (System.Uri uri, System.Threading.CancellationToken cancellationToken, System.Net.Http.HttpClient client) [0x00011] in D:\a\1\s\Xamarin.Forms.Core\StreamWrapper.cs:99 
  at Xamarin.Forms.Forms+AndroidPlatformServices.GetStreamAsync (System.Uri uri, System.Threading.CancellationToken cancellationToken) [0x0003f] in D:\a\1\s\Xamarin.Forms.Platform.Android\Forms.cs:854 
  at Xamarin.Forms.UriImageSource.GetStreamAsync (System.Uri uri, System.Threading.CancellationToken cancellationToken) [0x000cf] in D:\a\1\s\Xamarin.Forms.Core\UriImageSource.cs:136 

Long story short: I want to download an image and display it from the local file system. How do I do that?

Thanks a lot for the help.

Translated with www.DeepL.com/Translator (free version)

Mäxx
  • 13
  • 5
  • HttpClient only knows how to download http(s) destinations, not local files. You could probably use Glide/Nuke/FFImageloading or some other library to do this instead of doing it manually. – Cheesebaron Jan 17 '22 at 15:37
  • As @Cheesebaron said, you can use `FFImageLoading` to download your images and use cache to keep the image instead of download again. Then you decide when you want to show the images. – techie Jan 17 '22 at 19:59
  • And If the File is a Video or an Audio? – Mäxx Jan 17 '22 at 20:10
  • Manually means a converter? Or what is manually? Surely an image is capable of displaying a local image without an external library? – Mäxx Jan 17 '22 at 20:30
  • Seems like the ImageSource you are using is trying to download the image using HttpClient, rather display it from a local file. You are probably using the wrong ImageSource – Cheesebaron Jan 17 '22 at 20:32
  • That was my guess as well. How must the URL be structured to display a file from the LocaleStorage? – Mäxx Jan 17 '22 at 21:07

1 Answers1

1

I want to download an image and display it from the local file system. How do I do that?

The correct steps

  1. Download Image from remote url .

  2. Save it into disk locally .

  3. Get the steam data via the path(folder+fileName).

  4. Display it on Image .

This solution works well but in your scenario the difference that the image size is too big , so we just need to replace Xamarin.Essentials.Preferences with built-in File Handling, cause the later one can handle large file storage .

Modify the method SaveToDisk and GetFromDisk .

string folder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);

public static void SaveToDisk(string imageFileName, byte[] imageAsBase64String)
{  
    var fileName = Path.Combine(folder ,imageFileName);
    File.WriteAllText(fileName , Convert.ToBase64String(imageAsBase64String));
}

public static Xamarin.Forms.ImageSource GetFromDisk(string imageFileName)
{
    var fileName = Path.Combine(folder ,imageFileName);
    var imageAsBase64String = File.ReadAllText(fileName)
    return ImageSource.FromStream(() => new MemoryStream(Convert.FromBase64String(imageAsBase64String)));
}
ColeX
  • 14,062
  • 5
  • 43
  • 240