作為Web App訪問遠程圖片是經常的遇到功能,Wp本身提供了Image 很好的支持通過圖片的Uri顯示圖片
public ImageSource Source { get; set; }
<Image Source="https://www.google.com/intl/en_com/images/srpr/logo3w.png" />
為了減少網絡流量,需要將圖片緩存到本地數據存儲中。復習一下WP的本地數據存儲:
Windows Phone 本地數據存儲
Windows Phone 應用程序可以使用獨立存儲將數據儲存到手機本地。應用程序可以通過三種方式儲存數據:
- 設置:使用 IsolatedStorageSettings 類將數據存儲為鍵/值對。
- 文件和文件夾:使用 IsolatedStorageFile 類存儲文件和文件夾。
- 本地數據庫:7.1新增,只能支持LINQ TO SQL ,不能寫SQL語句。
本地存儲圖片
首先圖片應該選擇IsolatedStorageFile來存儲:
WP提供了一個叫IsolatedStorageFileStream的Stream和FileStream操作一樣
using (var fileStream = isolatedStorageFile.OpenFile(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
stream.CopyTo(fileStream);
}
緩存的思路
現在是思路是首先檢查是否被緩存里,首先定義一個公用的緩存文件夾,在靜態構造函數中創建文件夾
private const string CacheDirectory = "CachedImages";
static StorageCachedImage()
{
//創建緩存目錄
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!isolatedStorageFile.DirectoryExists(CacheDirectory))
{
isolatedStorageFile.CreateDirectory(CacheDirectory);
}
}
}
然后將Url轉換成文件名,我的方法比較簡單直接替換’/’符號。使用FileExists判斷文件是否存在
//文件路徑
filePath = Path.Combine(CacheDirectory, uriSource.AbsolutePath.TrimStart('/').Replace('/', '_'));
/// <summary>
/// 打開緩存源
/// </summary>
private void OpenCatchSource()
{
bool exist;
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
exist = isolatedStorageFile.FileExists(filePath);
}
if (exist)
{
SetCacheStreamSource();
}
else
{
SetWebStreamSource();
}
}
如果沒有緩存則通過Uri下載圖片並保存到IsolatedStorageFile。
使用httpWebRequest實現下載,使用IsolatedStorageFileStream保存圖片
/// <summary>
/// 下載Uri中的圖片
/// </summary>
private void SetWebStreamSource()
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(uriSource);
httpWebRequest.AllowReadStreamBuffering = true;
httpWebRequest.BeginGetResponse(ResponseCallBack, httpWebRequest);
}
/// <summary>
/// 下載回調
/// </summary>
/// <param name="asyncResult"></param>
private void ResponseCallBack(IAsyncResult asyncResult)
{
var httpWebRequest = asyncResult.AsyncState as HttpWebRequest;
if(httpWebRequest == null)return;
try
{
var response = httpWebRequest.EndGetResponse(asyncResult);
using(var stream = response.GetResponseStream())
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
using (var fileStream = isolatedStorageFile.OpenFile
(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
stream.CopyTo(fileStream);//保存到本地
}
Dispatcher.BeginInvoke(SetCacheStreamSource);
}
catch(Exception err)
{
Debug.WriteLine(err.Message);
}
}
保存到本地后下載,用IsolatedStorageFileStream打開本地圖像流,並通過父類的SetSource設置圖片流。
private void SetCacheStreamSource()
{
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = isolatedStorageFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
SetSource(stream);
}
完整代碼如下:

using System;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Net;
using System.Windows.Media.Imaging;
namespace KimiStudio.Controls
{
/// <summary>
/// 獨立存儲緩存的圖片源
/// </summary>
public sealed class StorageCachedImage : BitmapSource
{
private readonly Uri uriSource;
private readonly string filePath;
private const string CacheDirectory = "CachedImages";
static StorageCachedImage()
{
//創建緩存目錄
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!isolatedStorageFile.DirectoryExists(CacheDirectory))
{
isolatedStorageFile.CreateDirectory(CacheDirectory);
}
}
}
/// <summary>
/// 創建一個獨立存儲緩存的圖片源
/// </summary>
/// <param name="uriSource"></param>
public StorageCachedImage(Uri uriSource)
{
this.uriSource = uriSource;
//文件路徑
filePath = Path.Combine(CacheDirectory, uriSource.AbsolutePath.TrimStart('/').Replace('/', '_'));
OpenCatchSource();
}
/// <summary>
/// 打開緩存源
/// </summary>
private void OpenCatchSource()
{
bool exist;
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
exist = isolatedStorageFile.FileExists(filePath);
}
if (exist)
{
SetCacheStreamSource();
}
else
{
SetWebStreamSource();
}
}
/// <summary>
/// 設置緩存流到圖片
/// </summary>
private void SetCacheStreamSource()
{
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = isolatedStorageFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
SetSource(stream);
}
}
/// <summary>
/// 下載Uri中的圖片
/// </summary>
private void SetWebStreamSource()
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(uriSource);
httpWebRequest.AllowReadStreamBuffering = true;
httpWebRequest.BeginGetResponse(ResponseCallBack, httpWebRequest);
}
/// <summary>
/// 下載回調
/// </summary>
/// <param name="asyncResult"></param>
private void ResponseCallBack(IAsyncResult asyncResult)
{
var httpWebRequest = asyncResult.AsyncState as HttpWebRequest;
if(httpWebRequest == null)return;
try
{
var response = httpWebRequest.EndGetResponse(asyncResult);
using(var stream = response.GetResponseStream())
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
using (var fileStream = isolatedStorageFile.OpenFile
(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
stream.CopyTo(fileStream);
}
Dispatcher.BeginInvoke(SetCacheStreamSource);
}
catch(Exception err)
{
Debug.WriteLine(err.Message);
}
}
}
}
測試
定義一個Image
Uri uriSource = new Uri(@”https://www.google.com/intl/en_com/images/srpr/logo3w.png”);
image1.ImageSource = new StorageCachedImage(uriSource);
用IsoStoreSpy查看(這里是我APP實際的圖)