2019-9-2-win10-uwp-存放网络图片到本地
title | author | date | CreateTime | categories |
---|---|---|---|---|
win10 uwp 存放网络图片到本地
|
lindexi
|
2019-09-02 12:57:38 +0800
|
2018-2-13 17:23:3 +0800
|
Win10 UWP
|
有时候我们的网络很垃圾,我的的UWP要在第一次打开网络图片,就把图片存放到本地,下次可以从本地打开。
有时候用户使用的是流量网络,不能每次都联网下载。
我们不得在应用存放用户打开的图片。
这就是先把图片下载,然后显示出来,存放到本地,接着下次要使用就可以从本地获取。
最好这个和我们用户是透明,我们不知道图片在哪,是本地还是网络,只要给一个Uri就有一个图片。
这里图片我用BitmapImage,Uri是输入网络的
下载图片
图片也是和其他一样,我们可以简单用系统给的网络web下载。
我们需要输入Uri,然后把图片下载。
图片要显示,需要SetSourceAsync,他需要的参数IRandomAccessStream,而这个需要Buffer写数据,不能用byte,我开始用的System.Net.Http
没有获取Buffer方法,于是我查了垃圾wr,最后用Windows.Web.Http
先获取图片
Windows.Web.Http.HttpClient http = new Windows.Web.Http.HttpClient(); IBuffer buffer = await http.GetBufferAsync(uri); BitmapImage img = new BitmapImage(); using (IRandomAccessStream stream = new InMemoryRandomAccessStream()) { await stream.WriteAsync(buffer); stream.Seek(0); await img.SetSourceAsync(stream); await StorageImageFolder(stream, uri); return img; }
StorageImageFolder就是保存图片
保存图片
我们需要知道一个Uri就可以拿到一个图片,但是Uri不能做文件名,于是我用md5
Uwp使用Md5,可以去看我写的文章
private static string Md5(string str) { HashAlgorithmProvider hashAlgorithm = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5); CryptographicHash cryptographic = hashAlgorithm.CreateHash(); IBuffer buffer = CryptographicBuffer.ConvertStringToBinary(str, BinaryStringEncoding.Utf8); cryptographic.Append(buffer); return CryptographicBuffer.EncodeToHexString(cryptographic.GetValueAndReset()); }
我们的图片存放在本地,最后放在ApplicationData.Current.LocalCacheFolder
在存放文件,RandomAccessStream需要转byte[]
private static async Task<byte[]> ConvertIRandomAccessStreamByte(IRandomAccessStream stream) { DataReader read = new DataReader(stream.GetInputStreamAt(0)); await read.LoadAsync((uint)stream.Size); byte[] temp = new byte[stream.Size]; read.ReadBytes(temp); return temp; }
存放文件
string image = Md5(uri.AbsolutePath); StorageFile file = await folder.CreateFileAsync(image); await FileIO.WriteBytesAsync(file, await ConvertIRandomAccessStreamByte(stream));
从本地打开
把Uri转为图片名,打开本地文件
string name = Md5(uri.AbsolutePath); StorageFile file = await folder.GetFileAsync(name); using (var stream = await file.OpenAsync(FileAccessMode.Read)) { BitmapImage img = new BitmapImage(); await img.SetSourceAsync(stream); return img; }
所有代码
第一次使用图片从网络打开,第二次就可以放在本地,不使用网络。
先搜索本地,本地存在就打开,不存在只好从网络打开
函数使用就是ImageStorage.GetImage(uri);
public static class ImageStorage { /// <summary> /// 获取图片 /// 如果本地存在,就获取本地 /// 如果本地不存在,获取网络 /// </summary> /// <param name="uri"></param> /// <returns></returns> public static async Task<BitmapImage> GetImage(Uri uri) { return await GetLoacalFolderImage(uri) ?? await GetHttpImage(uri); } /// <summary> /// 从本地获取图片 /// </summary> /// <param name="uri"></param> private static async Task<BitmapImage> GetLoacalFolderImage(Uri uri) { StorageFolder folder = await GetImageFolder(); string name = Md5(uri.AbsolutePath); try { StorageFile file = await folder.GetFileAsync(name); using (var stream = await file.OpenAsync(FileAccessMode.Read)) { BitmapImage img = new BitmapImage(); await img.SetSourceAsync(stream); return img; } } catch (Exception) { return null; } } private static async Task<BitmapImage> GetHttpImage(Uri uri) { try { Windows.Web.Http.HttpClient http = new Windows.Web.Http.HttpClient(); IBuffer buffer = await http.GetBufferAsync(uri); BitmapImage img = new BitmapImage(); using (IRandomAccessStream stream = new InMemoryRandomAccessStream()) { await stream.WriteAsync(buffer); stream.Seek(0); await img.SetSourceAsync(stream); await StorageImageFolder(stream, uri); return img; } } catch (Exception) { return null; } } private static async Task StorageImageFolder(IRandomAccessStream stream, Uri uri) { StorageFolder folder = await GetImageFolder(); string image = Md5(uri.AbsolutePath); try { StorageFile file = await folder.CreateFileAsync(image); await FileIO.WriteBytesAsync(file, await ConvertIRandomAccessStreamByte(stream)); } catch (Exception) { } } private static async Task<byte[]> ConvertIRandomAccessStreamByte(IRandomAccessStream stream) { DataReader read = new DataReader(stream.GetInputStreamAt(0)); await read.LoadAsync((uint)stream.Size); byte[] temp = new byte[stream.Size]; read.ReadBytes(temp); return temp; } private static async Task<StorageFolder> GetImageFolder() { //文件夹 string name = "image"; StorageFolder folder = null; //从本地获取文件夹 try { folder = await ApplicationData.Current.LocalCacheFolder.GetFolderAsync(name); } catch (FileNotFoundException) { //没找到 folder = await ApplicationData.Current.LocalCacheFolder. CreateFolderAsync(name); } return folder; } private static string Md5(string str) { HashAlgorithmProvider hashAlgorithm = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5); CryptographicHash cryptographic = hashAlgorithm.CreateHash(); IBuffer buffer = CryptographicBuffer.ConvertStringToBinary(str, BinaryStringEncoding.Utf8); cryptographic.Append(buffer); return CryptographicBuffer.EncodeToHexString(cryptographic.GetValueAndReset()); } }
Nuget安装
Nuget搜索lindexi.uwp.src.ImageStorage
命令行
Install-Package lindexi.uwp.src.ImageStorage
Microsoft.Toolkit.Uwp
当前图片缓存的功能已经合并到 Microsoft.Toolkit.Uwp 工具,不过里面已经看不到我写的代码了,所以变得更加好用
在最低版本为 16299 之后可以通过 nuget 找到 Microsoft.Toolkit.Uwp 安装,然后可以使用下面的代码判断如果图片已经保存在本地,就从本地读取图片。如果图片没有保存到本地,就从网络下载
// 图片可以保存多久的时间
ImageCache.Instance.CacheDuration = TimeSpan.FromHours(24); // 最多可以在内存存放多少张图片
ImageCache.Instance.MaxMemoryCacheCount = 100; var distantUri = new Uri("http://www.myserver.com/image.jpg"); // 如果图片没有在缓存里,将会下载图片。如果图片在缓存里,直接返回图片
var bitmapImage = await ImageCache.Instance.GetFromCacheAsync(distantUri); // 清理缓存
await ImageCache.Instance.ClearAsync();
最新文章
- oracle内存粒度
- sessionStorage/localStorage 本地存储
- C#操作PPT表格
- Google Tensorflow 源码编译(一):Protobuf<;v3.0.0-alpha-3>;
- 通过WMI - Win32_Processor - ProcessorId获取到的并不是CPU的序列号,也并不唯一
- cmake编译dcmtk,并利用vs2010 进行开发mfc 程序
- 不会JS中的OOP,你也太菜了吧!(第二篇)
- USACO Section 2.4: The Tamworth Two
- poj 2479 (DP)
- [Everyday Mathematics]20150116
- poj2484--A Funny♂Game
- 201521123038 《Java程序设计》 第十四周学习总结
- 搭建nuxtjs程序 —— 用户信息 or token怎么不丢失
- HTTP与TCP的关系
- Windows Server 2016-Powershell新建用户补充
- [Swift]LeetCode924.尽量减少恶意软件的传播 | Minimize Malware Spread
- Java多线程(二)——常用的实现多线程的两种方式
- 【Android端ANR卡顿检测】BlockCanary检测
- React Native(十三)&mdash;&mdash;ios键盘挡住textInput
- vijos 运输计划 - 二分答案 - 差分 - Tarjan
热门文章
- OpenCASCADE点向圆柱面投影
- Linux RHEL7(CentOS7源) 安装 Nginx
- [原创]Java调用PageOffice在线打开数据库中保存的Word文件
- Python学习day03 - Python基础(1)
- Java基础(业务问题)
- 2019-8-31-C#-已知点和向量,求距离的点
- [TJOI2017]城市 【树的直径+暴力+优化】
- idea debug技巧
- Django项目:CRM(客户关系管理系统)--60--50PerfectCRM实现CRM客户报名流程学生合同URL随机码
- LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)