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();

ImageCache

最新文章

  1. oracle内存粒度
  2. sessionStorage/localStorage 本地存储
  3. C#操作PPT表格
  4. Google Tensorflow 源码编译(一):Protobuf&lt;v3.0.0-alpha-3&gt;
  5. 通过WMI - Win32_Processor - ProcessorId获取到的并不是CPU的序列号,也并不唯一
  6. cmake编译dcmtk,并利用vs2010 进行开发mfc 程序
  7. 不会JS中的OOP,你也太菜了吧!(第二篇)
  8. USACO Section 2.4: The Tamworth Two
  9. poj 2479 (DP)
  10. [Everyday Mathematics]20150116
  11. poj2484--A Funny♂Game
  12. 201521123038 《Java程序设计》 第十四周学习总结
  13. 搭建nuxtjs程序 —— 用户信息 or token怎么不丢失
  14. HTTP与TCP的关系
  15. Windows Server 2016-Powershell新建用户补充
  16. [Swift]LeetCode924.尽量减少恶意软件的传播 | Minimize Malware Spread
  17. Java多线程(二)——常用的实现多线程的两种方式
  18. 【Android端ANR卡顿检测】BlockCanary检测
  19. React Native(十三)&mdash;&mdash;ios键盘挡住textInput
  20. vijos 运输计划 - 二分答案 - 差分 - Tarjan

热门文章

  1. OpenCASCADE点向圆柱面投影
  2. Linux RHEL7(CentOS7源) 安装 Nginx
  3. [原创]Java调用PageOffice在线打开数据库中保存的Word文件
  4. Python学习day03 - Python基础(1)
  5. Java基础(业务问题)
  6. 2019-8-31-C#-已知点和向量,求距离的点
  7. [TJOI2017]城市 【树的直径+暴力+优化】
  8. idea debug技巧
  9. Django项目:CRM(客户关系管理系统)--60--50PerfectCRM实现CRM客户报名流程学生合同URL随机码
  10. LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)