问题描述
这是我以前的问题的扩展
this is an extension to my previous question how should a metro app cache images for tombstoning (and should it)?
我一直在寻找的解决方案是使用HttpClient,但这会导致Web服务器上每个文件不必要的第二次点击.
The solutions that I have been finding are to use HttpClient, but this results in an unnecessary second hit per file on the web server.
反正是否有从Image/ImageSource保存现有图像/流的信息(使用ImageOpened事件以确保其可用)?
Is there anyway to save the existing image/stream from a Image/ImageSource (using the ImageOpened event to ensure it is available) ?
解决方案必须与当前的RP API配合使用,因为这是CP进行了较大更改的领域.
Solution must work with current RP API as this is an area where large changes have been made from CP.
推荐答案
首先请注意,没有做任何自定义(即,使用URI作为Image.Source),已经实现了某种缓存,就好像您在您的应用程序旁边运行Fiddler时,您会看到请求发出一次,而不是每次显示项目时发出.
First of all please note, that without doing anything custom (i.e. using a URI as an Image.Source), there's already some kind of cache implemented as if you have a Fiddler running next to your app, you'll see that requests are issued once and not each time an item is displayed.
这就是说,如果您想要某种持久性缓存,则可以创建一个Converter,该转换器检查所需图像是否在应用程序的临时目录中,如果不是,则将其下载.
This being said, if you want some kind of persistent cache, you could create a Converter which checks if the desired image is in the App's temporary directory and downloads it if it's not the case.
这是一种方法:
public sealed class UriToCachedImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
Uri uri = value as Uri;
if (uri == null)
return null;
// Don't let user know those are images, yet keep a unique and consistent name.
string fileName = Path.GetFileName(uri.AbsolutePath);
StorageFile file = null;
try
{
Task<StorageFile> task = ApplicationData.Current.TemporaryFolder.GetFileAsync(fileName).AsTask<StorageFile>();
task.Wait();
file = task.Result;
}
catch (AggregateException ex)
{
if (ex.InnerException is FileNotFoundException)
{
// http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/1eb71a80-c59c-4146-aeb6-fefd69f4b4bb/
}
else
{
throw;
}
}
if (file == null)
{
// File isn't present in cache => download it.
// This creates a file in the app's INetCache
// but we can't retrieve its path or know its name for sure
// hence we're not using this file as our cache file.
Task<StorageFile> streamTask = StorageFile.CreateStreamedFileFromUriAsync(fileName, uri, RandomAccessStreamReference.CreateFromUri(uri)).AsTask<StorageFile>();
streamTask.Wait();
StorageFile storageFile = streamTask.Result;
// Copy file to our temporary directory (can't move as we don't have write access on the initial file).
Task<StorageFile> copyTask = storageFile.CopyAsync(ApplicationData.Current.TemporaryFolder, fileName, NameCollisionOption.ReplaceExisting).AsTask<StorageFile>();
copyTask.Wait();
file = copyTask.Result;
}
Task<IRandomAccessStreamWithContentType> openTask = file.OpenReadAsync().AsTask<IRandomAccessStreamWithContentType>();
openTask.Wait();
IRandomAccessStreamWithContentType randomAccessStream = openTask.Result;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(randomAccessStream);
return bitmapImage;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
注意:此代码段还说明了如何从同步方法中调用异步方法;)
Note: This code snippet also illustrates how to call async methods from a synchronous method ;)
这篇关于如何在不重新下载的情况下从ImageSource保存图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!