1. 程式人生 > >Unity使用C#網路下載使用者頭像

Unity使用C#網路下載使用者頭像

Unity使用C#網路下載使用者頭像


其實每個人中都會遇到在專案下載使用者頭像,下面是專案中使用的網路下載圖片,使用WWW從網路上下載到本地,本地獲取圖片,使用的Unity版本是2017.1,使用UGUI

封裝UnityEngine.WWW進行下載的類DownloadWWW .cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Linq;
using UnityEngine;

    /// <summary>
    /// 封裝UnityEngine.WWW進行下載的類
    /// </summary>
    public class DownloadWWW : MonoBehaviour
    {
    private static DownloadWWW instance;
    public static DownloadWWW Instance
    {
        get
        {
            if (instance == null)
            {
                GameObject obj = new GameObject();
                //obj.name = "DownloadWWW";
                instance = obj.AddComponent<DownloadWWW>();
            }
            return instance;
        }
    }
    private void Awake()
    {
        DontDestroyOnLoad(gameObject);
    }




    /// <summary>
    /// 下載url資源的文字內容
    /// </summary>
    /// <param name="url">url資源</param>
    /// <param name="isAddRandomParams">是否新增隨機引數</param>
    /// <param name="callback">下載完畢回撥函式</param>
    /// <param name="retryCount">本次下載失敗後的重試次數</param>
    public void DownloadText(string url, bool isAddRandomParams, Action<bool, string> callback, Action<float> progress, int retryCount)
        {
            if (isAddRandomParams)
                url = GetRandomParamsUrl(url);
            Debug.Log("URL:" + url);
            StartCoroutine(DoDownloadText(url, callback, progress, retryCount));
        }

        private IEnumerator DoDownloadText(string url, Action<bool, string> callback, Action<float> progress, int retryCount)
        {
            var www = new WWW(url);
            while (!www.isDone)
            {
                if (progress != null)
                    progress(www.progress);
                yield return null;
            }
            if (progress != null)
                progress(www.progress);
            if (string.IsNullOrEmpty(www.error))
            {
                if (callback != null)
                    callback(true, www.text);
            }
            else
            {
                if (retryCount <= 0)
                {
                    // 徹底失敗
                    Debug.LogError(string.Concat("DownloadText Failed!  URL: ", url, ", Error: ", www.error));
                    if (callback != null)
                        callback(false, null);
                }
                else
                {
                    // 繼續嘗試
                    yield return StartCoroutine(DoDownloadText(url, callback, progress, --retryCount));
                }
            }
        }

        /// <summary>
        /// 下載url資源的位元組內容
        /// </summary>
        /// <param name="url">url資源</param>
        /// <param name="isAddRandomParams">是否新增隨機引數</param>
        /// <param name="callback">下載完畢回撥函式</param>
        /// <param name="retryCount">本次下載失敗後的重試次數</param>
        public void DownloadBytes(string url, bool isAddRandomParams, Action<bool, byte[]> callback, Action<float> progress, int retryCount)
        {
            if (isAddRandomParams)
                url = GetRandomParamsUrl(url);
            Debug.Log("URL:" + url);
            StartCoroutine(DoDownloadBytes(url, callback, progress, retryCount));
        }

        private IEnumerator DoDownloadBytes(string url, Action<bool, byte[]> callback, Action<float> progress, int retryCount)
        {
            var www = new WWW(url);
            while (!www.isDone)
            {
                if (progress != null)
                    progress(www.progress);
                yield return null;
            }
            if (progress != null)
                progress(www.progress);
            if (string.IsNullOrEmpty(www.error))
            {
                if (callback != null)
                    callback(true, www.bytes);
            }
            else
            {
                if (retryCount <= 0)
                {
                    // 徹底失敗
                    Debug.LogError(string.Concat("DownloadBytes Failed!  URL: ", url, ", Error: ", www.error));
                    if (callback != null)
                        callback(false, null);
                }
                else
                {
                    // 繼續嘗試
                    yield return StartCoroutine(DoDownloadBytes(url, callback, progress, --retryCount));
                }
            }
        }

        /// <summary>
        /// 給原始url加上隨機引數
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private string GetRandomParamsUrl(string url)
        {
            var r = new System.Random();
            var u = string.Format("{0}?type={1}&ver={2}&sign={3}", url.Trim(), r.Next(100), r.Next(100), Guid.NewGuid().ToString().Substring(0, 8));
            return u;
        }

        /// <summary>
        /// 訪問http
        /// </summary>
        /// <param name="url"></param>
        /// <param name="onDone"></param>
        /// <param name="onFail"></param>
        public void GetHttp(string url, Action<string> onDone, Action<string> onFail)
        {
            Debug.Log("URL:" + url);
            StartCoroutine(DoGetHttp(url, onDone, onFail));
        }

        private IEnumerator DoGetHttp(string url, Action<string> onDone, Action<string> onFail)
        {
            WWW www = new WWW(url);
            yield return www;
            if (string.IsNullOrEmpty(www.error))
            {
                onDone(www.text);
            }
            else
            {
                Debug.Log("HttpResponse onFail:" + www.error);
                onFail(www.error);
            }
        }
    }

HTTP下載HttpManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.IO;
using System;
using System.Text;
using UnityEngine.UI;

/// <summary>
/// HTTP下載
/// </summary>
public class HttpManager : MonoBehaviour {

   
    private static HttpManager instance;
    public static HttpManager Instance
    {
        get
        {
            if (instance == null)
            {
                GameObject obj = new GameObject();
                obj.name = "HttpManager";
                instance = obj.AddComponent<HttpManager>();
            }
            return instance;
        }
    }
    /// <summary>
    /// web下載物體
    /// </summary>
    private  GameObject webDownloaderObj;
    /// <summary>
    /// 下載類
    /// </summary>
    private  DownloadWWW downloadWWW;
    /// <summary>
    /// 快取字典
    /// </summary>
    private  Dictionary<string, Texture2D> dicHeadTextureMd5;
    /// <summary>
    /// 下載的圖相list
    /// </summary>
    private  List<string> lisHeadName;//預備下載影象清單
    //private void Awake()
    //{
        
    //}
    void Start () {
        Init();
    }
    public  void Init()
    {
        webDownloaderObj = new GameObject("WebDownloader");
        downloadWWW = webDownloaderObj.AddComponent<DownloadWWW>();
        dicHeadTextureMd5 = new Dictionary<string, Texture2D>();
    }

    /// <summary>
    /// 手機記憶體讀取圖片
    /// </summary>
    public Texture2D LoadTexture2DInStorage(string url)
    {
        //建立檔案讀取流
        FileStream fileStream = new FileStream(url, FileMode.Open, FileAccess.Read);
        fileStream.Seek(0, SeekOrigin.Begin);
        //建立檔案長度緩衝區
        byte[] bytes = new byte[fileStream.Length];
        //讀取檔案
        fileStream.Read(bytes, 0, (int)fileStream.Length);
        //釋放檔案讀取流
        fileStream.Close();
        fileStream.Dispose();
        fileStream = null;

        //建立Texture
        int width = 50;
        int height = 50;
        Texture2D texture = new Texture2D(width, height, TextureFormat.RGB24, false);
        texture.LoadImage(bytes);
        return texture;
    }
    /// <summary>
    /// 字典初始化
    /// </summary>
    private  void InitTempTextture()
    {
        if (dicHeadTextureMd5 == null)
        {
            dicHeadTextureMd5 = new Dictionary<string, Texture2D>();

        }
           
    }
    /// <summary>
    /// 清單初始化
    /// </summary>
    private  void InitTempLisName()
    {
        if (lisHeadName == null)
            lisHeadName = new List<string>();
    }
    /// <summary>
    /// 檢測字典是否包含該圖片
    /// </summary>
    /// <param name="textureName"></param>
    /// <returns></returns>
    public  bool IshaveTempTextture(string textureName)
    {
        return (dicHeadTextureMd5.ContainsKey(textureName));
    }
    /// <summary>
    /// 臨時儲存圖片到字典
    /// </summary>
    /// <param name="textureName"></param>
    /// <param name="texture2D"></param>
    public  void SaveTempDicTextture(string textureName, Texture2D texture2D)
    {
        if (!dicHeadTextureMd5.ContainsKey(textureName))
            dicHeadTextureMd5.Add(textureName, texture2D);
    }
    /// <summary>
    /// 從字典讀取圖片
    /// </summary>
    /// <param name="textureName"></param>
    /// <returns></returns>
    public  Texture2D LoadTempDicTextture(string textureName)
    {
        return dicHeadTextureMd5[textureName];
    }
    /// <summary>
    /// 載入預設頭像,並存入字典(臨時儲存)
    /// </summary>
    /// <returns></returns>
    public  Texture2D LoadDefaultTexture(string texNameMd5)
    {
        Texture2D defTex = Resources.Load<Texture2D>("Face/headdefault");//載入預設頭像
        SaveTempDicTextture(texNameMd5, defTex);//存入字典(臨時儲存)
        return defTex;
    }
    public void LoadImage(string url,GameObject path)
    {
        RawImage rawImage = path.GetComponent<RawImage>();
        if (rawImage != null)
        {
            StartCoroutine(LoadHead(url, rawImage));
        }
        
    }
    /// <summary>
    /// 頭像載入
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public  IEnumerator LoadHead(string url, RawImage logo)
    {
        int tryCount = 0;
        while (tryCount < 10)//下載嘗試次數
        {
            bool andios = (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer);
            string texName = url;//圖片名稱.Remove(0, url.LastIndexOf("/") + 1)
            string texNameMd5 = RegularExpression.MD5Encrypt32(texName);//圖片名稱加密md5
                                                                        //Debug.Log(texName + "  " + texNameMd5);+
            string directoryPath = "";//圖片資料夾路徑
            string directoryMd5Path = "";//圖片檔案完整路徑
            bool isLoad = false;//是否開始下載,否則讀記憶體
            InitTempTextture();
            InitTempLisName();//初始化清單
            if (!lisHeadName.Contains(texNameMd5))
            {
                lisHeadName.Add(texNameMd5);
                isLoad = true;//不存在則新增入清單,並進入下載模式
            }
            yield return 0;//下一幀後檢測全域性
            if (!isLoad)
            {
                float waitTime = 0;
                while (!IshaveTempTextture(texNameMd5) && waitTime < 1.5f) { waitTime += Time.deltaTime; yield return 0; }//字典是否含該圖片,等待快出現的記憶體
                if (waitTime < 1.5f)
                {
                    if(logo)
                        logo.texture = LoadTempDicTextture(texNameMd5);//顯示//有則直接讀取記憶體
                }
                else logo.texture = LoadDefaultTexture(texNameMd5);
                tryCount = 10; break;//結束
            }
            else
            {   //無則開始圖片載入過程
                if (andios)
                {   ///手機無則建立資料夾
                    //directoryPath = "D:/" + "/headimage";//
                    directoryPath = Application.persistentDataPath + "/headimage";//資料夾路徑
                    Debug.Log("<color=yellow>圖片儲存路徑:::"+ directoryPath + "</color>");
                    if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath);//無則建立資料夾
                    while (!Directory.Exists(directoryPath)) { yield return 0; }//建立時間,檢測資料夾是否存在
                    directoryMd5Path = directoryPath + "/" + texNameMd5;//圖片檔案完整路徑

                    //讀取手機記憶體中資料夾裡的圖片
                    if (File.Exists(directoryMd5Path))
                    {
                        Debug.Log("匯入手機記憶體圖片");
                        Texture2D newTex = LoadTexture2DInStorage(directoryMd5Path);//讀取
                        logo.texture = newTex;//顯示
                        Debug.Log("<color = #FFD505>  +++++++        " + newTex.name + "+++++++++++++++++ </color> ");
                        SaveTempDicTextture(texNameMd5, newTex);//存入字典(臨時儲存)
                        tryCount = 10; break;//結束
                    }
                }
                if (!andios || (andios && !File.Exists(directoryMd5Path)))
                {//從伺服器下載圖片後存入記憶體
                    if (url.Length <= 10)
                    {//長度不夠則為無效url,載入預設頭像
                        logo.texture = LoadDefaultTexture(texNameMd5);
                        tryCount = 10; break;//結束                        
                    }
                    else
                    {//長度夠則為有效url,下載頭像
                        WWW www = new WWW(url);
                        yield return www; Debug.Log("頭像下載完畢");
                  
                       
                      
                        if (string.IsNullOrEmpty(www.error))
                        {   //www快取時有缺陷,2種方式存記憶體
                            Texture2D wwwTex = new Texture2D(www.texture.width, www.texture.height, TextureFormat.RGB24, false);
                            www.LoadImageIntoTexture(wwwTex);
                            //Texture2D wwwTex = www.texture;
                            logo.texture = wwwTex;//顯示
                            SaveTempDicTextture(texNameMd5, wwwTex);//存入字典(臨時儲存)
                            if (andios && !File.Exists(directoryMd5Path)) WebTestDownload(url, directoryMd5Path);//存入手機記憶體
                            while (!File.Exists(directoryMd5Path)) { yield return 0; }
                            Texture2D newTex = LoadTexture2DInStorage(directoryMd5Path);//讀取內建
                            SaveTempDicTextture(texNameMd5, newTex);//存入字典(臨時儲存)
                            tryCount = 10; break;//結束
                        }
                        else tryCount++;//重新下載嘗試+1
                    }

                }
            }
        }

    }
    /// <summary>
    /// web下載
    /// </summary>
    /// <param name="url"></param>
    /// <param name="isAddRandomParams"></param>
    /// <param name="callback"></param>
    /// <param name="progress"></param>
    public  void DownloadBytes(string url, bool isAddRandomParams = true, Action<bool, byte[]> callback = null, Action<float> progress = null)
    {
        if (downloadWWW == null) Init();
        downloadWWW.DownloadBytes(url, isAddRandomParams, callback, progress, 3);
    }

    /// <summary>
    /// 使用協程下載檔案
    /// </summary>
    public void WebTestDownload(string url, string filepath)
    {
        //string url = "http://192.168.70.88:8000/Android/weekly/last/1001.prefab.k_d4a807497e976cbadd197c90160ef3ee";
        DownloadBytes(url, true, (ok, bytes) =>
        {
            if (ok)
            {
                //string filepath = Application.persistentDataPath + "/1001.prefab.k";
                File.WriteAllBytes(filepath, bytes);
                Debug.Log("Download Success: " + filepath + ", " + File.Exists(filepath));
            }

        });
    }


    /// <summary>
    /// 連線htttp請求 解析返回內容
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
	public string HttpGet(string url)
    {
        string str=null;
        HttpWebRequest res = (HttpWebRequest)WebRequest.Create(url);
        res.Method = "GET";
        res.ContentType = "text/html;charset=UTF-8";

        HttpWebResponse response = (HttpWebResponse)res.GetResponse();
        Stream strRes = response.GetResponseStream();
        StreamReader read = new StreamReader(strRes,Encoding.GetEncoding("utf-8"));
        str = read.ReadToEnd();
        Debug.Log(str);
        strRes.Close();
        read.Close();
        return str;
    }

}

怎麼使用呢?只需要在場景中一個物體上掛載HttpManager.cs,
HttpManager httpManager = go.GetComponent《HttpManager》();//去它身上拿到HttpManager指令碼
httpManager.LoadImage(imageURL, obj);//傳入下載地址和需要改變圖片的物體