AR在Unity3D中实现扫描下载断点续传 — HttpWebRequest

1.使用AssetBundle压缩资源上传到服务器
使用AssetBundle压缩资源上传到服务器
由于测试需要,可以把需要的数据模型等,直接放到服务器上。本人直接将需要下载的视频资源放到七流云空间。
编写脚本,不需要挂在任何物体上,Unity3D会检测到打包脚本,打包方法如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;                             //导入系统相关类

public class BUNAssets : MonoBehaviour {

    [@MenuItem("Test/Build Asset Bundles")]         //添加菜单栏"Test”以及子菜 单"Build Asset Bundles”       
    //声明BuildAssetBundles方法
       // 打包位置到指定文件夹下
    static void BuildAssetBundles()
    {   
        BuildPipeline.BuildAssetBundles(Application.dataPath + "/Assetbundle", BuildAssetBundleOptions.UncompressedAssetBundle,BuildTarget.iOS);
    }
}

2.个人最近研究的是EasyAR的官方SDK ,其中主要脚本官方已经给出,个人开发可以根据官方给的脚本进行操作实施,脚本编程如下

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
using System.Net;
using UnityEngine.UI;
using System.Threading;
//using UnityEngine.UI;
namespace EasyAR
{
    public class EasyImageTargetBehaviour : ImageTargetBehaviour
    {

        bool isDone;
//      Image image;
         Text text;
        float localprogress ;
        HttpDownLoad http;


        public string BundleURL;
        public string AssetName ; // 预控件名称
        // strat 方法
        protected override void Awake()
        {
            BundleURL = Application.dataPath + "/Assetbundle/workroom.mp4";
            text = GameObject.Find ("Canvas/Text").gameObject.GetComponent<Text> (); //进度条文字 拿到项目上悬挂的脚本找到Text控件
            base.Awake();
            TargetFound += OnTargetFound;
            TargetLost += OnTargetLost;
            TargetLoad += OnTargetLoad;
            TargetUnload += OnTargetUnload;
        }
            
        protected void Update()
        {
//          if (System.IO.File.Exists (Application.dataPath + "/Assetbundle/workroom.mp4") == true) {
//              return;
//          }
            text.text = "资源加载中" + (http.progress * 100).ToString ("0.00") + "%";    

            if(http.progress == 1)
            {
                if (System.IO.File.Exists (Application.dataPath + "/Assetbundle/1164.mov") == true) {
                    Debug.Log ("Update 中 拿到下载完毕----");
                    isDone = false;
                    Destroy(GameObject.Find("Canvas/Text")); //销毁资源
                    http.Close ();
                }
            }
        }
        void OnTargetFound(TargetAbstractBehaviour behaviour)
        {
            Debug.Log("OnTargetFound: " + Target.Id +Target.Name);
                if (System.IO.File.Exists (Application.dataPath +"/Assetbundle/1164.mov") == false) {
//                  StartCoroutine (progress1.DownloadVideo (@"http://ot24avzj3.bkt.clouddn.com/1164.mov", Application.dataPath +"/Assetbundle/1164.mov"));
//                  判断异步对象并且异步对象没有加载完毕,显示进度    
                    http = new HttpDownLoad();
    http.DownLoad(@"http://ot24avzj3.bkt.clouddn.com/1164.mov", Application.dataPath +"/Assetbundle/1164.mov", LoadLevel);
//                  Down_List ();

                return;
            }

//  该处需根据个人需要加载个人所需要的资源
//          AssetBundle modelBundle = AssetBundle.LoadFromFile (BundleURL); //根据文本路径找到打包的数据
//          GameObject model = modelBundle.LoadAsset (AssetName) as GameObject;//根据预控件的名字加载模型
//          if (model != null) {
//              Instantiate (model); //实例化模型
//          }
//          model.transform.position = new Vector3 (-10f, 0f, 0f); // 设置位置
//          modelBundle.Unload (false);//卸载资源
        }

        void LoadLevel()
        {
            isDone = true;
        }


        void OnTargetLost(TargetAbstractBehaviour behaviour)
        {
            Debug.Log("Lost: " + Target.Id);
            if (Target.Name == "koala") {
                text.text = "";
                http.Close ();
            }
        }

        void OnTargetLoad(ImageTargetBaseBehaviour behaviour, ImageTrackerBaseBehaviour tracker, bool status)
        {
            Debug.Log("Load target (" + status + "): " + Target.Id + " (" + Target.Name + ") " + " -> " + tracker);
        }

        void OnTargetUnload(ImageTargetBaseBehaviour behaviour, ImageTrackerBaseBehaviour tracker, bool status)
        {
            Debug.Log("Unload target (" + status + "): " + Target.Id + " (" + Target.Name + ") " + " -> " + tracker);
        }
    
}

3.下载脚本,编程如下。
涉及的知识点有

1. 线程的使用 Thread
2. 流文件的操作 FileStream
3. 网络下载 HttpWebRequest(同理也可以使用官方在推崇的WWW方式,个人使用过之后觉得大多已被封装,可扩展操作性空间较小)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.IO;
using System;
using System.Threading;

public class HttpDownLoad{

    //下载进度
    public float progress{get; private set;} //C#私有属性,set 前面加private 告诉编译器属性是只读的,外部不能给属性赋值,只能读取其值
    //涉及子线程要注意,Unity关闭的时候子线程不会关闭,所以要有一个标识
    private bool isStop;
    //子线程负责下载,否则会阻塞主线程,Unity界面会卡主
    public Thread thread;
    //表示下载是否完成
    public bool isDone{get; private set;}

    const int oneReadLen = 16384;           // 一次读取长度 16384 = 16*kb
    const int ReadWriteTimeOut = 2 * 1000;  // 超时等待时间
    const int TimeOutWait = 5 * 1000;       // 超时等待时间
    const int MaxTryTime = 3;

    /// <summary>
    /// 下载方法(断点续传)
    /// </summary>
    /// <param name="url">URL下载地址</param>
    /// <param name="savePath">Save path保存路径</param>
    /// <param name="callBack">Call back回调函数</param>
    public void DownLoad(string downUrl, string savePath, Action callBack)
    {
        if (System.IO.File.Exists (savePath) == true  ) { //如果本地文件存在储存路劲则
            return;
        }
        isStop = false;
        //开启子线程下载,使用匿名方法

        thread = new Thread(delegate() {
            //打开上次下载的文件
            long startPos = 0;
            string tempFile = savePath+".temp";
            FileStream fs = null; // 文件
            //使用流操作文件
            if (File.Exists(tempFile))
            {
                fs = File.OpenWrite(tempFile);
                startPos = fs.Length;

            }
            else
            {
                string direName = Path.GetDirectoryName(tempFile); //返回指定路径字符串的目录信息
                if (!Directory.Exists(direName)) Directory.CreateDirectory(direName); //在direName目录下创建目录
                fs = new FileStream(tempFile, FileMode.Create);//创建流文件
            }
            //获取文件现在的长度
            long fileLength = fs.Length;
            //获取下载文件的总长度
            long totalLength = GetLength(downUrl);
            //如果没下载完
            if(fileLength < totalLength)
            {
                //断点续传核心,设置本地文件流的起始位置
                fs.Seek(fileLength, SeekOrigin.Begin);
                //创建网络请求
                HttpWebRequest request = HttpWebRequest.Create(downUrl) as HttpWebRequest;

                //断点续传核心,设置远程访问文件流的起始位置
                request.AddRange((int)fileLength);
                Stream  stream = request.GetResponse().GetResponseStream();
                byte[] buffer = new byte[1024];
                //使用流读取内容到buffer中
                //注意方法返回值代表读取的实际长度,并不是buffer有多大,stream就会读进去多少
                int length = stream.Read(buffer, 0, buffer.Length);
                while(length > 0)
                {
                    //如果Unity客户端关闭,停止下载
                    if(isStop) break;
                    //将内容再写入本地文件中
                    fs.Write(buffer, 0, length);
                    //计算进度
                    fileLength += length;

                    // 判断是否下载完成
                    if (fileLength == totalLength)
                    {
                        fs.Flush();// 清除该流的所有缓冲区,使得所有缓冲的数据都被写入到基础设备
                        fs.Close();// 关闭流
                        fs = null;
                        if (File.Exists(savePath)) File.Delete(savePath);
                        File.Move(tempFile, savePath);  // 下载完成将temp文件,改成正式文件
                    }
                    progress = (float)fileLength / (float)totalLength;
                    UnityEngine.Debug.Log(progress);
                    //类似尾递归
                    length = stream.Read(buffer, 0, buffer.Length); // 返回读入缓冲区的最大字节
                }
                stream.Close();    // 关闭链接
                stream.Dispose(); //  这个链接不需要了,可以释放资源

            }
            else
            {
                progress = 1;
                fs.Flush();
                fs.Close();
                fs = null;
                if (File.Exists(savePath)) File.Delete(savePath); //如果文件里存在了,就删了
                File.Move(tempFile, savePath);
            
            }
            fs.Close();
            fs.Dispose();
            //如果下载完毕,执行回调
            if(progress == 1)
            {
                isDone = true;
                if(callBack != null) callBack();
            }

        });
        //开启子线程
        thread.IsBackground = true;
        thread.Start();

    }


    /// <summary>
    /// 获取下载文件的大小
    /// </summary>
    /// <returns>The GetLength.</returns>
    /// <param name="url">URL.</param>

    public static long GetLength(string url)
    {
        HttpWebRequest request = null;
        WebResponse respone = null;
        long length = 0;
        try
        {
            request = WebRequest.Create(url) as HttpWebRequest;
//          request.Timeout = TimeOutWait;
//          request.ReadWriteTimeout = ReadWriteTimeOut;
            //向服务器请求,获得服务器回应数据流
            respone = request.GetResponse();
            length = respone.ContentLength;
        }
        catch (WebException e)
        {
            throw e;
        }
        finally
        {
            if (respone != null) respone.Close();
            if (request != null) request.Abort();
        }
        return length;
    }

    public void Close()
    {
        isStop = true;
    }


}

Unity3D小白,研究过程主要参考技术博客如下:
Unity技术博客 - 客户端断点续传
转载合作相关事宜,请联系我的经纪人。额,还没有经纪人,联系本人,转载系出处,谢谢。

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

推荐阅读更多精彩内容