2020-11-03 Unity 使用UnityWebRequest下载图片 音频 APk等功能实现

在工作中经常会需要下载网络图片,或者音频等功能,所以封装了这个下载脚本。
功能需求:为了高效率和节省流量,再本地有该文件时不再重复下载
可以回传下载进度,下载后的资源
调用方式简单

用来下载的脚本

using UnityEngine;
using System.Collections;
using System.IO;
using System;
using UnityEngine.Networking;

/// <summary>
/// 图片缓存
/// </summary>
public class WebUtils : SingletonObject<WebUtils>
{

    /// <summary>
    /// 下载带泛型
    /// </summary>
    public  void Load<T>(string url , Action<T> endAction=null, Action<float> proAction=null) where T: UnityEngine.Object
    {
        if (!string.IsNullOrEmpty(url))
        {
            string path = PathTools.GetSavePath(url);
            if (!File.Exists(path))
            {
                StartCoroutine(DownLoadByUnityWebRequest<T>(url, endAction, proAction));
            }
            else//已在本地缓存  
            {
                StartCoroutine(DownLoadByUnityWebRequest<T>(path, endAction, proAction));
            }
        }
        else 
        {
            Debug.LogError("WebUtils error: url is null!");
        }
    }

    /// <summary>
    /// UnityWebRequest下载
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="url">地址</param>
    /// <param name="type">下载类型</param>
    /// <param name="callback">结束回调</param>
    /// <param name="proAction">进度回调</param>
    /// <returns></returns>
    private IEnumerator DownLoadByUnityWebRequest<T>(string url, Action<T> callback = null,Action<float> proAction=null) where T : UnityEngine.Object
    {
        UnityWebRequest uwr = new UnityWebRequest(url);

        if (typeof(T) == typeof(AudioClip)) 
        {
            string _suf = PathTools.GetSuffix(url);
            AudioType at = AudioType.MPEG;
            if (_suf.Contains("ogg"))
                at = AudioType.OGGVORBIS;
            DownloadHandlerAudioClip downloadAudioClip = new DownloadHandlerAudioClip(url, at);
            uwr.downloadHandler = downloadAudioClip;
        }

        if (typeof(T) == typeof(Sprite)|| typeof(T) == typeof(Texture2D))
        {
            DownloadHandlerTexture downloadTexture = new DownloadHandlerTexture(true);
            uwr.downloadHandler = downloadTexture;
        }

        uwr.SendWebRequest();
        while (true)
        {
            if (uwr.isNetworkError || uwr.isHttpError)
                break;

            if (uwr.isDone || uwr.downloadProgress >= 1) 
            {
                proAction?.Invoke(1);
                break;
            }
            else
                proAction?.Invoke(uwr.downloadProgress);
        }

        yield return uwr;

        if (!uwr.isNetworkError && !uwr.isHttpError)
        {
            if (typeof(T) == typeof(AudioClip))
            {
                AudioClip audioClip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip;
                callback.Invoke((T)(UnityEngine.Object)audioClip);
            }

            if (typeof(T) == typeof(Sprite))
            {
                Texture2D texture = ((DownloadHandlerTexture)uwr.downloadHandler).texture;
                Sprite sp = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.one * 0.5f);
                callback?.Invoke((T)(UnityEngine.Object)sp);
            }

            if (typeof(T) == typeof(Texture2D))
            {
                Texture2D texture1 = ((DownloadHandlerTexture)uwr.downloadHandler).texture;
                callback?.Invoke((T)(UnityEngine.Object)texture1);
            }

            //保存到本地
            if (url.Substring(0, 4) == "http")
            {
                File.WriteAllBytes(PathTools.GetSavePath(url), uwr.downloadHandler.data);
            }
        }
        else 
        {
            Debug.LogError("DownLoadByUnityWebRequest error:"+ uwr.error +"  url:"+url);
        }
    }


    /// <summary>
    /// 下载文件
    /// </summary>
    public void LoadFile(string url,string _suffix="", Action<string> endAction = null, Action<float> proAction = null) 
    {
        if (!string.IsNullOrEmpty(url+_suffix))
        {
            string path = PathTools.GetSavePath(url+_suffix);
            if (!File.Exists(path))
            {
                StartCoroutine(DownLoadFileByUnityWebRequest(url, _suffix, endAction, proAction));
            }
            else//已在本地缓存  
            {
                StartCoroutine(DownLoadFileByUnityWebRequest(path, _suffix, endAction, proAction));
            }
        }
        else
        {
            Debug.LogError("WebUtils error: url is null!");
        }
    }

    private IEnumerator DownLoadFileByUnityWebRequest(string url, string _suffix = "", Action<string> callback = null, Action<float> proAction = null) 
    {
       UnityWebRequest uwr =  UnityWebRequest.Get(url);
        uwr.SendWebRequest();

        while (true)
        {
            if (uwr.isNetworkError || uwr.isHttpError)
                break;

            if (uwr.isDone || uwr.downloadProgress >= 1)
            {
                proAction?.Invoke(1);
                break;
            }
            else
                proAction?.Invoke(uwr.downloadProgress);
        }

        yield return uwr;

        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.LogError("DownLoadByUnityWebRequest error:" + uwr.error + "  url:" + url);
        }
        else 
        {
            callback?.Invoke(uwr.downloadHandler.text.ToString());
            //保存到本地
            if (url.Substring(0, 4) == "http")
            {
                File.WriteAllBytes(PathTools.GetSavePath(url + _suffix), uwr.downloadHandler.data);
            }
        }
    }

}


路径工具脚本

using System.IO;
using UnityEngine;

/// <summary>
/// 路径工具
/// </summary>
public class PathTools
{
    /// <summary>
    /// StreamPath路径
    /// </summary>
    public static string StreamPath
    {
        get
        {
            return Application.streamingAssetsPath + "/Cache";
        }
    }

    /// <summary>
    /// 缓存路径
    /// </summary>
    public static string persistentPath
    {
        get
        {
            return Application.persistentDataPath + "/WebCache";
        }
    }

    static  string[] sufTypes = { "png","jpg","apk","mp3","ogg","txt","json"}; 
    /// <summary>
    /// 获取资源的保存路径
    /// </summary>
    public static string GetSavePath(string url) 
    {
        string _suffix = GetSuffix(url);
        string _name = "{0}." + _suffix;
        string path = Path.Combine(persistentPath, _suffix);
        CreatePath(path);
        path = Path.Combine(path, string.Format(_name, GetFileName(url)/*url.GetHashCode()*/)); ;
        return path;
    }

    /// <summary>
    /// 解析后缀名
    /// </summary>
    public static string GetFileName(string url)
    {
        string[] subArr = url.Split('.');
        string totalStr = subArr[subArr.Length - 2];
        string [] subArr1 = totalStr.Split('/');
        return subArr1[subArr1.Length-1];
    }

    /// <summary>
    /// 解析后缀名
    /// </summary>
    public static string GetSuffix(string url) 
    {
        string[] subArr = url.Split('.');
        string _suffix  = subArr[subArr.Length - 1];

        for (int i = 0; i < sufTypes.Length; i++)
        {
            if (_suffix.Contains(sufTypes[i]))
            {
                _suffix = sufTypes[i];
                break;
            }
        }
        return _suffix;
    }

    /// <summary>
    /// 获取资源的加载路径
    /// </summary>
    public static string GetLoadPath(string url)
    {
        return "file:///" + GetSavePath(url);
    }

    /// <summary>
    /// 创建路径
    /// </summary>
    static void CreatePath(string path) 
    {
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
    }

    /// <summary>
    /// 获取资源保存路径,打包时保存路径
    /// </summary>
    public static string GetAssetOutPath(int target)
    {
        string path = "";
        switch (target)
        {
            case 5://win
                path = StreamPath + "/Android/";
                break;
            case 9://ios
                path = StreamPath + "/IOS/";
                break;
            case 13://android
                path = StreamPath + "/Android/";
                break;
        }
        return path;
    }

    /// <summary>
    /// 不同平台下StreamingAssets的路径
    /// </summary>
    public static readonly string dataPath =
#if UNITY_ANDROID && !UNITY_EDITOR
        "jar:file://" + Application.dataPath + "!/assets/";
#elif UNITY_IOS && !UNITY_EDITOR
        "file://" + Application.dataPath + "/Raw/";
#elif UNITY_STANDALONE_WIN
        "file://" + Application.dataPath + "/StreamingAssets/";
#else
        "file://" + Application.dataPath + "/StreamingAssets/";
#endif


    /// <summary>
    /// 平台名称,下载时只区分安卓和ios,pc使用安卓的资源
    /// </summary>
    public static readonly string platName =
#if UNITY_IOS 
         "IOS";
#else
       "Android";
#endif
}



调用方式

   WebUtils.Ins.Load<Sprite>(imgurl, (sp) =>
        {

            image.sprite = sp;
            Debug.Log("下载结束");

        }, (pro) =>
        {

            Debug.Log("进度:" + pro);

        });


        WebUtils.Ins.Load<AudioClip>(audurl, (cp) =>
        {

            GetComponent<AudioSource>().clip = cp;
            GetComponent<AudioSource>().Play();
            Debug.Log("下载结束");

        }, (pro) =>
        {

            Debug.Log("进度:" + pro);

        });


        WebUtils.Ins.LoadFile(apkurl, (str) => {

            Debug.Log("下载结束:"+str);

        }, (pro) => {

            Debug.Log("进度:" + pro);

        });

再封装一下

using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 加载工具
/// </summary>
public class LoadUtils
{

    /// <summary>
    ///  通过图集设置图片
    /// </summary>
    public static void SetChildImage(Image image, string url,string name)
    {
        Sprite[] sprs = Resources.LoadAll<Sprite>(url);

        if (sprs != null && sprs.Length > 0)
        {
            foreach (var item in sprs)
            {
                if (item.name == name)
                {
                    image.sprite = item;
                }
            }
        }
        else
        {
            Debug.LogError("SetChildImage url error:"+url);
        }
    }

    /// <summary>
    /// 设置图片
    /// </summary>
    /// <param name="url"> 地址</param>
    /// <param name="image"> 图片 </param>
    /// <param name="befor"> Resource下路径  填空直接再Resource中加载 </param>
    public static void SetImage(string url,Image image, string befor ="")
    {
        if (string.IsNullOrEmpty(url) || image == null)
        {
            return;
        }
        //网图
        if (url.Substring(0, 4) == "http")
        {
            WebUtils.Ins.Load<Sprite>(url, (sp) =>
            {
                image.sprite = sp;
            });
        }
        else //Resources加载
        {
            string[] strs = url.Split('.');
            if (strs.Length > 1) 
            {
                url = strs[0];
            }

            url = befor +"/"+ url;

            Sprite spri = ResourceLoader.Ins.Load<Sprite>(url);

            if (spri != null)
            {
                image.sprite = spri;
            }
            else
            {
                Debug.LogError("LoadUtils SetImage error: " + url);
            }
        }
    }

    /// <summary>
    /// 设置音频
    /// </summary>
    public static void SetAudio(string url, AudioSource audio, string befor = "")
    {
        if (string.IsNullOrEmpty(url) || audio == null)
        {
            return;
        }

        if (url.Substring(0, 4) == "http")
        {
            WebUtils.Ins.Load<AudioClip>(url, (clip) =>
            {
                audio.clip = clip;
                audio.Play();
            });
        }
        else
        {
            string[] strs = url.Split('.');
            if (strs.Length > 1) 
            {
                url = strs[0];
            }

            url = befor + url;
            AudioClip clip = ResourceLoader.Ins.Load<AudioClip>(url);
            audio.clip = clip;
            audio.Play();
        }
    }

}

调用

        LoadUtils.SetImage("icon_chongwu_moren@2x", image, "Texture");
        LoadUtils.SetAudio("2147463780", GetComponent<AudioSource>());
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352