/// <summary> /// Caches the given object to the Application's ImageCache /// and returns the uri of the cached file. /// </summary> /// <param name="objectToCache">Object to cache</param> /// <param name="cacheFileName">Name of the cache file</param> /// <param name="progressHandler">Delegate for handling progress</param> /// <returns>Uri</returns> public Task <Uri> GetCachedUriAsync(object objectToCache, string cacheFileName, CacheProgressHandler progressHandler = null) { // Check if the objectToCache is a valid Uri var uri = objectToCache as Uri; if (uri == null) { // Is the objectToCache a string representing a Uri? var uriString = objectToCache as string; if (uriString != null) { // Try creating the Uri from the uriString if (!(Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out uri))) { return(null); } } } // Caching indicates only 80% of the task completed i.e. 80% progress, // Progress will be 100% only when the image is loaded successfully on the ImageFrame progressHandler?.Invoke(80); // Since the given Uri is contained within the Application data or package, there // is no need to cache it. Just return the same uri. return(Task.Run(() => uri)); }
/// <summary> /// Since the given Uri is contained within the Application data or package, there /// is no need to cache it. Just return the same uri. /// </summary> /// <param name="uri">Uri to cache</param> /// <param name="cacheFileName">Hash of the Uri</param> /// <param name="progressHandler">Delegate for handling progress</param> /// <returns>Uri</returns> public Task <Uri> GetCachedUriAsync(Uri uri, string cacheFileName, CacheProgressHandler progressHandler = null) { // Caching indicates only half of the task completed i.e. 50% progress, // Progress will be 100% only when the image is loaded successfully on the // CompositionImageFrame progressHandler?.Invoke(50); return(Task.Run(() => uri)); }
/// <summary> /// Caches the given object to the Application's ImageCache /// and returns the uri of the cached file. /// </summary> /// <param name="objectToCache">Object to cache</param> /// <param name="cacheFileName">Name of the cache file</param> /// <param name="progressHandler">Delegate for handling progress</param> /// <returns>Uri</returns> public async Task <Uri> GetCachedUriAsync(object objectToCache, string cacheFileName, CacheProgressHandler progressHandler = null) { // Check if the objectToCache is a valid IRandomAccessStream var stream = objectToCache as IRandomAccessStream; if ((stream == null) || !stream.CanRead) { return(null); } // Calculate the expiry date var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration); // Get the cache folder location var cacheFolder = await ImageCache.GetCacheFolderAsync(); if (cacheFolder == null) { return(null); } // Report Progress progressHandler?.Invoke(0); // Get the cache file corresponding to the cacheFileName var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile; // Has the cache file expired or does it not exist? if (await cacheFile.IsNullOrExpired(expirationDate)) { try { // Create/Recreate the cache file cacheFile = await cacheFolder.CreateFileAsync(cacheFileName, CreationCollisionOption.ReplaceExisting); // Open the cache file for writing using (var cacheStream = await cacheFile.OpenAsync(FileAccessMode.ReadWrite)) { // Start reading the content as a stream using (var inputStream = stream.GetInputStreamAt(0)) { ulong totalBytesRead = 0; var prevProgress = -1; var totalContentLength = stream.Size; if (totalContentLength <= 0UL) { prevProgress = 0; } while (true) { // Read from the stream IBuffer buffer = new Windows.Storage.Streams.Buffer(2048); buffer = await inputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None); if (buffer.Length == 0) { // There is nothing else to read break; } // The following code can be used to report progress totalBytesRead += buffer.Length; if (totalContentLength > 0UL) { // We will report a progress percent between 0%-80% because caching represents 80% // of the task of displaying the image. The other 20% requires successful loading // of the cached image. var progress = (int)Math.Round((totalBytesRead * 80) / (double)totalContentLength); if (progress != prevProgress) { // Report Progress progressHandler?.Invoke(progress); prevProgress = progress; } } else { prevProgress = Math.Min(prevProgress + 1, 80); // Report Progress progressHandler?.Invoke(prevProgress); } // Write to cache file await cacheStream.WriteAsync(buffer); } } } } catch (Exception) { // In case any exception occurs during the copying of the StorageFile // delete the cacheFile and return a 'null' Uri cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile; if (cacheFile != null) { await cacheFile.DeleteAsync(); } // Report Progress progressHandler?.Invoke(-1); return(null); } } // Report Progress // Caching indicates only half of the task completed i.e. 50% progress, // Progress will be 100% only when the image is loaded successfully on the ImageFrame progressHandler?.Invoke(80); // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile return(new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}")); }
/// <summary> /// Caches the given object to the Application's ImageCache /// and returns the uri of the cached file. /// </summary> /// <param name="objectToCache">Object to cache</param> /// <param name="cacheFileName">Name of the cache file</param> /// <param name="progressHandler">Delegate for handling progress</param> /// <returns>Uri</returns> public async Task <Uri> GetCachedUriAsync(object objectToCache, string cacheFileName, CacheProgressHandler progressHandler = null) { // Check if the objectToCache is a valid Uri var uri = objectToCache as Uri; if (uri == null) { // Is the objectToCache a string representing a Uri? var uriString = objectToCache as string; if (uriString != null) { // Try creating the Uri from the uriString if (!(Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out uri))) { return(null); } } } // Calculate the expiry date var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration); // Get the cache folder location var cacheFolder = await ImageCache.GetCacheFolderAsync(); if (cacheFolder == null) { return(null); } // Report Progress progressHandler?.Invoke(0); // Get the cache file corresponding to the cacheFileName var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile; // Has the cache file expired or does it not exist? if (await cacheFile.IsNullOrExpired(expirationDate)) { try { // Create/Recreate the cache file cacheFile = await cacheFolder.CreateFileAsync(cacheFileName, CreationCollisionOption.ReplaceExisting); using (var httpClient = new HttpClient()) { // Use HttpCompletionOption.ResponseHeadersRead for the GetAsync call so that it returns as // soon as response headers are received and not when the whole response is received using (var response = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead)) { // If respose status is not success then raise exception response.EnsureSuccessStatusCode(); // Open the cache file for writing using (var cacheStream = await cacheFile.OpenAsync(FileAccessMode.ReadWrite)) { // Start reading the content as a stream using (var inputStream = await response.Content.ReadAsInputStreamAsync()) { ulong totalBytesRead = 0; var prevProgress = -1; var totalContentLength = response.Content.Headers.ContentLength ?? 0UL; while (true) { // Read from the stream IBuffer buffer = new Windows.Storage.Streams.Buffer(2048); buffer = await inputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None); if (buffer.Length == 0) { // There is nothing else to read break; } // The following code can be used to report progress totalBytesRead += buffer.Length; if (totalContentLength > 0UL) { // We will report a progress percent between 0%-80% because caching represents 80% // of the task of displaying the image. The other 20% requires successful loading // of the cached image. var progress = (int)Math.Round((totalBytesRead * 80) / (double)totalContentLength); if (progress != prevProgress) { // Report Progress progressHandler?.Invoke(progress); prevProgress = progress; } } else { prevProgress = Math.Min(prevProgress + 1, 80); // Report Progress progressHandler?.Invoke(prevProgress); } // Write to cache file await cacheStream.WriteAsync(buffer); } } } } } } catch (Exception) { // In case any exception occurs during the downloading or caching // delete the cacheFile and return a 'null' Uri cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile; if (cacheFile != null) { await cacheFile.DeleteAsync(); } // Report Progress progressHandler?.Invoke(-1); return(null); } } // Report Progress // Caching indicates only half of the task completed i.e. 50% progress, // Progress will be 100% only when the image is loaded successfully on the ImageFrame progressHandler?.Invoke(80); // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile return(new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}")); }
/// <summary> /// Caches the given object to the Application's ImageCache /// and returns the uri of the cached file. /// </summary> /// <param name="objectToCache">Object to cache</param> /// <param name="cacheFileName">Name of the cache file</param> /// <param name="progressHandler">Delegate for handling progress</param> /// <returns>Uri</returns> public async Task <Uri> GetCachedUriAsync(object objectToCache, string cacheFileName, CacheProgressHandler progressHandler = null) { // Check if the objectToCache is a valid StorageFile var inputFile = objectToCache as StorageFile; if (inputFile == null) { return(null); } // Calculate the expiry date var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration); // Get the cache folder location var cacheFolder = await ImageCache.GetCacheFolderAsync(); if (cacheFolder == null) { return(null); } // Report Progress progressHandler?.Invoke(0); // Get the cache file corresponding to the cacheFileName var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile; // Has the cache file expired or does it not exist? if (await cacheFile.IsNullOrExpired(expirationDate)) { try { // Report Progress progressHandler?.Invoke(10); // Copy the storage file to the cacheFolder. If the file already exists, overwrite it await inputFile.CopyAsync(cacheFolder, cacheFileName, NameCollisionOption.ReplaceExisting); // Report Progress // Caching indicates only 80% of the task completed i.e. 80% progress, // Progress will be 100% only when the image is loaded successfully on the ImageFrame progressHandler?.Invoke(80); } catch (Exception) { // In case any exception occurs during the copying of the StorageFile // delete the cacheFile and return a 'null' Uri cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile; if (cacheFile != null) { await cacheFile.DeleteAsync(); } // Report Progress progressHandler?.Invoke(-1); return(null); } } // Report Progress progressHandler?.Invoke(80); // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile return(new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}")); }