/// <summary>
        /// 下载完成.
        /// </summary>
        /// <param name="iTargetID">目标ID.</param>
        /// <param name="iFileType">文件类型.</param>
        public void DownloadCompleted(string iTargetID, TUploadFileType iFileType)
        {
            lock (_targetUpdateLock) {
                DownloadTargetInfo downloadInfo = null;
                if (this.isTargetExist(iTargetID, iFileType, out downloadInfo) == true)
                {
                    if (downloadInfo == null)
                    {
                        return;
                    }
                    downloadInfo.Downloaded = true;

                    if (this._progressCounter != null)
                    {
                        this._progressCounter.UpdateCompletedCount();

                        long dataSize = (string.IsNullOrEmpty(downloadInfo.DataSize) == true) ? 0 : Convert.ToInt64(downloadInfo.DataSize);
                        this._progressCounter.UpdateCompletedDataSize(dataSize);

                        this.Info("DownloadCompleted()::Count({0}/{1}) DataSize({2}/{3})",
                                  this._progressCounter.DidCount, this._progressCounter.TotalCount,
                                  this._progressCounter.DidDatasize, this._progressCounter.TotalDatasize);
                    }
                }
            }
        }
        /// <summary>
        /// 判断目标存不存在.
        /// </summary>
        /// <returns><c>true</c>, 存在, <c>false</c> 不存在.</returns>
        /// <param name="iBundleId">BundleID.</param>
        /// <param name="iFileType">文件类型.</param>
        /// <param name="iTarget">下载目标信息.</param>
        public bool isTargetExist(string iBundleId,
                                  TUploadFileType iFileType, out DownloadTargetInfo iTarget)
        {
            iTarget = null;
            if (string.IsNullOrEmpty(iBundleId) == true)
            {
                return(false);
            }

            DownloadTargetInfo[] targets = this.Targets
                                           .Where(o => (
                                                      (iBundleId.Equals(o.ID) == true) &&
                                                      (iFileType == o.FileType)))
                                           .OrderByDescending(o => o.No)
                                           .ToArray();
            if ((targets == null) || (targets.Length <= 0))
            {
                return(false);
            }
            if (1 != targets.Length)
            {
                this.Warning("isTargetExist()::There is duplicate id exist in download list!!!(Bundle ID:{0} FileType:{1})",
                             iBundleId, iFileType);
            }
            iTarget = targets [0];
            return(true);
        }
        /// <summary>
        /// 添加对象.
        /// </summary>
        /// <param name="iTarget">对象.</param>
        /// <param name="iFileType">上传文件类型.</param>
        /// <param name="iHashCode">HashCode(Unity3d打包生成).</param>
        public void AddTarget(
            BundleMap iTarget, TUploadFileType iFileType, string iHashCode = null)
        {
            if (iTarget == null)
            {
                return;
            }
            UploadItem _item    = null;
            string     filePath = GetLocalBundleFilePath(
                iTarget.ID, iFileType, (TBundleType.Scene == iTarget.Type));
            string checkCode = null;

            string dataSize = null;

            if ((false == string.IsNullOrEmpty(filePath)) &&
                (true == File.Exists(filePath)))
            {
                if (TCheckMode.Unity3d_Hash128 == this.CheckMode)
                {
                    checkCode = iHashCode;
                }
                else
                {
                    checkCode = GetFileMD5(filePath);
                }
                FileInfo fileInfo = new FileInfo(filePath);
                dataSize = fileInfo.Length.ToString();
            }
            else
            {
                this.Warning("AddTarget()::Target File is not exist!!!(target:{0})", filePath);
            }

            bool _exist = this.isTargetExist(iTarget.ID, iFileType, out _item);

            if (false == _exist)
            {
                _item           = this.CreateUploadItem(iTarget.ID, iTarget.Type, iFileType);
                _item.CheckCode = checkCode;
                _item.DataSize  = dataSize;
            }
            else
            {
                if ((false == string.IsNullOrEmpty(checkCode)) &&
                    (false == checkCode.Equals(_item.CheckCode)))
                {
                    _item.CheckCode = checkCode;
                    _item.DataSize  = dataSize;
                    _item.Uploaded  = false;
                }
            }
            UtilsAsset.SetAssetDirty(this);
        }
        /// <summary>
        /// 取得Bundle全路径名.
        /// </summary>
        /// <returns>Bundle全路径名.</returns>
        /// <param name="iBundleId">BundleId.</param>
        /// <param name="iFileType">文件类型.</param>
        public string GetBundleFullPath(
            string iBundleId, TUploadFileType iFileType = TUploadFileType.Bundle)
        {
            DownloadTargetInfo targetInfo = null;

            if (isTargetExist(iBundleId, iFileType, out targetInfo) == false)
            {
                this.Error("GetBundleFullPath()::This bundles is not exist!!!({BundleId:{0} FileType:{1})",
                           iBundleId, iFileType);
                return(null);
            }
            if (targetInfo == null)
            {
                return(null);
            }
            string fileName = UploadList.GetLocalBundleFileName(iBundleId, targetInfo.FileType);

            if (string.IsNullOrEmpty(fileName) == true)
            {
                return(null);
            }

            string fileFullPath = null;

            switch (targetInfo.BundleType)
            {
            case TBundleType.Normal:
            {
                fileFullPath = string.Format("{0}/{1}",
                                             ServersConf.BundlesDirOfNormal,
                                             fileName);
            }
            break;

            case TBundleType.Scene:
            {
                fileFullPath = string.Format("{0}/{1}",
                                             ServersConf.BundlesDirOfScenes,
                                             fileName);
            }
            break;

            default:
            {
                fileFullPath = string.Format("{0}/{1}",
                                             ServersConf.BundlesDir,
                                             fileName);
            }
            break;
            }
            return(fileFullPath);
        }
        /// <summary>
        /// 取得本地上传用的输入文件地址.
        /// </summary>
        /// <returns>上传用的输入文件地址.</returns>
        /// <param name="iBundleId">Bundle ID.</param>
        /// <param name="iFileType">文件类型.</param>
        /// <param name="iIsScene">场景标志位.</param>
        public static string GetLocalBundleFilePath(
            string iBundleId, TUploadFileType iFileType, bool iIsScene)
        {
            string fileName = GetLocalBundleFileName(iBundleId, iFileType);

            if (iIsScene == true)
            {
                return(string.Format("{0}/{1}",
                                     UploadList.GetInstance().BundlesOutputDirOfScene, fileName));
            }
            else
            {
                return(string.Format("{0}/{1}",
                                     UploadList.GetInstance().BundlesOutputDirOfNormal, fileName));
            }
        }
        /// <summary>
        /// 创建UploadItem.
        /// </summary>
        /// <returns>UploadItem.</returns>
        /// <param name="iTargetId">目标ID.</param>
        /// <param name="iBundleType">Bundle类型.</param>
        /// <param name="iFileType">文件类型.</param>
        private UploadItem CreateUploadItem(
            string iTargetId, TBundleType iBundleType,
            TUploadFileType iFileType)
        {
            UploadItem objRet = new UploadItem();

            if (objRet != null)
            {
                objRet.No         = this.GetBundleNo();
                objRet.ID         = iTargetId;
                objRet.BundleType = iBundleType;
                objRet.FileType   = iFileType;
                objRet.Uploaded   = false;
                this.Targets.Add(objRet);
            }
            return(objRet);
        }
        /// <summary>
        /// 上传完成.
        /// </summary>
        /// <param name="iTargetID">目标ID.</param>
        /// <param name="iFileType">文件类型.</param>
        public void UploadCompleted(string iTargetID, TUploadFileType iFileType)
        {
            lock (_targetsThreadLock) {
                UploadItem uploadItem = null;
                if (true == this.isTargetExist(iTargetID, iFileType, out uploadItem))
                {
                    if (uploadItem == null)
                    {
                        return;
                    }
                    uploadItem.Uploaded = true;
                    if (this._progressCounter != null)
                    {
                        this._progressCounter.UpdateCompletedCount();

                        long dataSize = (string.IsNullOrEmpty(uploadItem.DataSize) == true) ? 0 : Convert.ToInt64(uploadItem.DataSize);
                        this._progressCounter.UpdateCompletedDataSize(dataSize);
                    }
                }
            }
        }
        /// <summary>
        /// 判断目标是否存在.
        /// </summary>
        /// <returns><c>true</c>,存在, <c>false</c> 不存在.</returns>
        /// <param name="iTargetID">目标ID.</param>
        /// <param name="iFileType">文件类型.</param>
        /// <param name="iTarget">目标信息.</param>
        private bool isTargetExist(string iTargetID, TUploadFileType iFileType, out UploadItem iTarget)
        {
            iTarget = null;

            UploadItem[] targets = this.Targets
                                   .Where(o => (
                                              (true == iTargetID.Equals(o.ID)) &&
                                              (iFileType == o.FileType)))
                                   .OrderBy(o => o.No)
                                   .ToArray();
            if ((targets == null) || (targets.Length <= 0))
            {
                return(false);
            }
            if (1 != targets.Length)
            {
                this.Warning("isTargetExist()::There is duplicate id exist in upload list!!!(Bundle ID:{0})", iTargetID);
            }
            iTarget = targets [0];
            return(true);
        }
        /// <summary>
        /// 取得本地上传用的输入文件名.
        /// </summary>
        /// <returns>上传用的输入文件名.</returns>
        /// <param name="iBundleId">Bundle ID.</param>
        /// <param name="iFileType">文件类型.</param>
        public static string GetLocalBundleFileName(
            string iBundleId, TUploadFileType iFileType)
        {
            string fileName = iBundleId;

            switch (iFileType)
            {
            case TUploadFileType.Bundle:
            {
                string fileSuffix = UploadList.GetInstance().FileSuffix;
                if (string.IsNullOrEmpty(fileSuffix) == false)
                {
                    fileName = string.Format("{0}.{1}", fileName, fileSuffix);
                }
            }
            break;

            case TUploadFileType.NormalManifest:
            {
                string fileSuffix = UploadList.GetInstance().FileSuffix;
                if (string.IsNullOrEmpty(fileSuffix) == false)
                {
                    fileName = string.Format("{0}.{1}", fileName, fileSuffix);
                }
                fileName = string.Format("{0}.manifest", fileName);
            }
            break;

            case TUploadFileType.MainManifest:
            default:
            {
            }
            break;
            }
            return(fileName);
        }