2019年1月25日 星期五

Unity使用HttpWebRequest + URL 下載檔案

本篇要介紹在Unity使用HttpWebRequest下載檔案到手機或是電腦裡。

一、設定圖片存放的位置
//指定到對應環境的路徑
public class utilPath
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
    public static string LOCAL_PATH = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
#elif (UNITY_ANDROID)
    public static string LOCAL_PATH = Application.persistentDataPath;
#endif 
}

//設定要存放的路徑(ImageCache跟Image可以自定義名稱)
public string path
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
        get { return utilPath.LOCAL_PATH + "\\DownLoad\\"; }
#elif (UNITY_ANDROID)
        get { return utilPath.LOCAL_PATH + "/DownLoad/"; }
#endif
}
二、檢查是否下載過檔案
/// 避免重複開啟同一個檔案,File_state 為enum自定義的檔案狀態
/// url為下載路徑、file_name為資料夾內檔名
public FileState CheckFileState(string url, string file_name)
{
   if (File.Exists(path + file_name))
   {
      file_stream = File.OpenRead(path + file_name);
      start_Length = file_stream.Length;
      file_stream.Close();

      total_Length = GetLength(url);

      if(start_Length < total_Length)               
          File_state = FileState.loading;
      else
          File_state = FileState.isDone;
      }
      else
          File_state = FileState.empty;

      return File_state;
    }
}

/// 獲取下載文件的大小
long GetLength(string url)
{
    //路徑的檔名 跟 server上的apk檔名 不同的情況下,WebRequest仍然可以create,但Response會傳出錯誤(error 404)
    HttpWebRequest request_Length = HttpWebRequest.Create(url) as HttpWebRequest;
    request_Length.Method = "HEAD";
    HttpWebResponse response_Length = request_Length.GetResponse() as HttpWebResponse;

    response_Length.Close();
    return response_Length.ContentLength;
}
三、檔案下載
//定義一個下載檔案的資料類型(class)
public class FileData
{
    const int m_buffetSize = 1024;
    public byte[] m_bufferRead;
    public string FileName;
    public HttpWebRequest m_request;
    public HttpWebResponse m_response;
    public Stream m_streamResponse;

    public FileData(string name)
    {
        m_bufferRead = new byte[8*m_buffetSize];
        FileName = name;
        m_request = null;
        m_response = null;
        m_streamResponse = null;
    }
}

//啟動重頭/中途下載
private bool File_Request(FileData file, string url)
{
    try
    {
        if (File.Exists(path + file.FileName))
        {
            //檔案存在!!取得已下載部分
            //Debug.Log("File is Exist to Get FileLength ~~");
            file_stream = File.OpenWrite(path + file.FileName);
            start_Length = file_stream.Length;
            file_stream.Seek(start_Length, SeekOrigin.Current);
        }
        else
        {
            file_stream = new FileStream(path + file.FileName, FileMode.Create);
            start_Length = 0L;
        }
        request = (HttpWebRequest)WebRequest.Create(url);

        if (start_Length > 0)
            request.AddRange((int)start_Length);

        //實體類中將http的請求信息也帶進去了,方便回調中的判斷
        file.m_request = request;
        //ResponseCallbackDownLoad請求成功後的回調方法
        request.BeginGetResponse(new AsyncCallback(ResponseCallbackDownLoad), file);

        downDelayTime = 0;
        isDownload = true;
        return true;
   }
   catch(Exception ex)
   {
        Debug.Log(ex.Message);
        return false;
   }
}

//BeginGetResponse成功時回調函式
private void ResponseCallbackDownLoad(IAsyncResult ar)
{
    try
    {
        obj_req = ar.AsyncState as object;
        if (obj_req == null)
            return;

        temp_file = ar.AsyncState as FileData;
        temp_file.m_response = temp_file.m_request.EndGetResponse(ar) as HttpWebResponse; 
        if(temp_file.m_response.StatusCode == HttpStatusCode.OK || temp_file.m_response.StatusCode == HttpStatusCode.PartialContent)
        {
            //Debug.Log("Download AsynFile Req End");
            temp_file.m_streamResponse = temp_file.m_response.GetResponseStream();
            try
            {
                //Debug.Log("Get New File ~~");
                Stop_Flag = false;
                //獲取文件總長度
                fileLength = temp_file.m_response.ContentLength;
                //如果是續傳的情況 總長 = 已下載 + 剩餘的
                if (temp_file.m_response.StatusCode == HttpStatusCode.PartialContent)
                   fileLength += start_Length;

                //下載的文件長度
                fileSize = start_Length;

                temp_progress = 0;
                readCount = temp_file.m_streamResponse.Read(temp_file.m_bufferRead, 0, temp_file.m_bufferRead.Length);
                  
                while (readCount > 0)
                {
                    downDelayTime = 0;
                    file_stream.Write(temp_file.m_bufferRead, 0, readCount);

                    fileSize += readCount;
                    //progress 為計算下載的百分比
                    Progress = (int)(((float)fileSize / (float)fileLength) * 100);

                    if (Progress - temp_progress >= 1)
                    {
                        temp_progress = Progress;
                    }
                    readCount = temp_file.m_streamResponse.Read(temp_file.m_bufferRead, 0, temp_file.m_bufferRead.Length);
                    if (!isDownload)
                        return;
                }

                //確保資料是抓完的/最後的回傳
                if (fileSize >= fileLength)
                {
                    //Debug.Log("File is DownLoad FIN  !!! fileSize ~~" + fileSize + "  fileLength ~~" + fileLength);
                    reDownloadCount = 0;
                }
            }
            catch 
                Debug.Log("error" );
        }
        else
        {
            temp_file.m_response.Close();
            Debug.Log("file.m_response.StatusCode = " + temp_file.m_response.StatusCode.ToString());
        }
    }
    catch
    {
        Debug.Log("文件下載失敗 = ");
        if (DownLoadEvent != null)
            DownLoadEvent(-1);
    }

    file_stream.Close();
    temp_file.m_response.Close();
    temp_file.m_streamResponse.Close();
    isDownload = false;
}
以上就是檔案下載的作法,這只是其中一種,有興趣可以上網找找其他的做法d(`・∀・)b

沒有留言:

張貼留言