示例#1
0
        // 指定的文件清单复制到本地目录
        public static IEnumerator CopyStreamingAssets(string outputPath, FileListManifest fileListManifest,
                                                      Action oncomplete)
        {
            var count = fileListManifest.files.Count;

            for (var i = 0; i < count; i++)
            {
                var file       = fileListManifest.files[i];
                var outputFile = Path.Combine(outputPath, file.name);
                if (!File.Exists(outputFile))
                {
                    var streamingAssetsFilePath = GetStreamingAssetsFilePath(file.name);
                    var uwr = UnityWebRequest.Get(streamingAssetsFilePath);
                    yield return(uwr.SendWebRequest());

                    if (uwr.error == null && uwr.responseCode == 200)
                    {
                        try
                        {
                            var bytes    = uwr.downloadHandler.data;
                            var checksum = Crc16.ComputeChecksum(bytes);
                            var size     = bytes.Length;
                            var metaFile = Path.Combine(outputPath, file.name + Metadata.Ext);
                            var metadata = new Metadata()
                            {
                                checksum = Crc16.ToString(checksum),
                                size     = size,
                            };
                            var metaJson = JsonUtility.ToJson(metadata);
                            File.WriteAllText(metaFile, metaJson);
                            File.WriteAllBytes(outputFile, bytes);
                        }
                        catch (Exception exception)
                        {
                            Debug.LogWarningFormat("CopyStreamingAssets exception: {0}\n{1}",
                                                   streamingAssetsFilePath, exception);
                        }
                    }
                    else
                    {
                        Debug.LogWarningFormat("CopyStreamingAssets request failed {0}: {1} {2}",
                                               streamingAssetsFilePath, uwr.responseCode,
                                               uwr.error);
                    }
                }
            }

            oncomplete?.Invoke();
        }
示例#2
0
        private void _HttpDownload(string url, int partialSize, byte[] buffer, Utils.Crc16 crc, Stream targetStream, int timeout)
        {
            PrintDebug($"downloading from {url}");
            var uri = new Uri(url);
            var req = WebRequest.CreateHttp(uri);

            req.Method           = WebRequestMethods.Http.Get;
            req.ContentType      = BundleContentType;
            req.ReadWriteTimeout = 10000;
            if (timeout > 0)
            {
                req.Timeout = timeout * 1000;
            }
            if (partialSize > 0)
            {
                req.AddRange(partialSize);
            }
            using (var rsp = req.GetResponse())
            {
                using (var webStream = rsp.GetResponseStream())
                {
                    var recvAll = 0L;
                    while (recvAll < rsp.ContentLength)
                    {
                        var recv = webStream.Read(buffer, 0, buffer.Length);
                        if (recv > 0 && _running)
                        {
                            recvAll += recv;
                            targetStream.Write(buffer, 0, recv);
                            crc.Update(buffer, 0, recv);
                            _progress = Mathf.Clamp01((float)(recvAll + partialSize) / _size);
                            if (_slow > 0)
                            {
                                Thread.Sleep(_slow); // 模拟低速下载
                            }
                            // PrintDebug($"{recvAll + partialSize}, {_size}, {_progress}");
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            // PrintDebug($"download exited");
        }
示例#3
0
        // 打开指定的清单文件 (带校验)
        public static Manifest ParseManifestFile(string filePath, FileEntry fileEntry, string password)
        {
            if (File.Exists(filePath))
            {
                using (var fs = File.OpenRead(filePath))
                {
                    var crc = new Crc16();
                    crc.Update(fs);
                    if (crc.hex == fileEntry.checksum && fs.Length == fileEntry.size)
                    {
                        fs.Seek(0, SeekOrigin.Begin);
                        return(ParseManifestStream(fs, fileEntry, password));
                    }
                }
            }

            return(null);
        }
示例#4
0
        private void DownloadExec(object state)
        {
            var        buffer     = new byte[BufferSize];
            var        tempPath   = _finalPath + PartExt;
            var        metaPath   = _finalPath + Metadata.Ext;
            var        retry      = 0;
            FileStream fileStream = null;

            while (true)
            {
                string error       = null;
                var    crc         = new Utils.Crc16();
                var    partialSize = 0;
                var    success     = true;
                if (fileStream == null)
                {
                    try
                    {
                        if (File.Exists(tempPath)) // 处理续传
                        {
                            var fileInfo = new FileInfo(tempPath);
                            fileStream  = fileInfo.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite);
                            partialSize = (int)fileInfo.Length;
                            if (partialSize > _size) // 目标文件超过期望大小, 直接废弃
                            {
                                fileStream.SetLength(0);
                                partialSize = 0;
                            }
                            else if (partialSize <= _size) // 续传
                            {
                                crc.Update(fileStream);
                                PrintDebug($"partial check {partialSize} && {_size} ({crc.hex})");
                            }
                        }
                        else // 创建下载文件
                        {
                            fileStream = File.Open(tempPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                            fileStream.SetLength(0);
                        }
                    }
                    catch (Exception exception)
                    {
                        // PrintError($"file exception: {exception}");
                        error   = $"file exception: {exception}";
                        success = false;
                    }
                }
                else
                {
                    fileStream.SetLength(0L);
                }

                if (success && (_size <= 0 || partialSize < _size))
                {
                    try
                    {
                        _HttpDownload(this.url, partialSize, buffer, crc, fileStream, _timeout);
                    }
                    catch (Exception exception)
                    {
                        // PrintError($"network exception: {exception}");
                        error   = $"network exception: {exception}";
                        success = false;
                    }
                }

                if (success && fileStream.Length != _size)
                {
                    if (_size > 0)
                    {
                        // PrintError($"filesize exception: {fileStream.Length} != {_size}");
                        error   = $"wrong file size: {fileStream.Length} != {_size}";
                        success = false;
                    }
                    else
                    {
                        _size = (int)fileStream.Length;
                    }
                }
                else if (success && crc.hex != _checksum)
                {
                    if (_checksum != null)
                    {
                        // PrintError($"checksum exception: {crc.hex} != {_checksum}");
                        error   = $"corrupted file: {crc.hex} != {_checksum}";
                        success = false;
                    }
                    else
                    {
                        _checksum = crc.hex;
                    }
                }

                lock (this)
                {
                    if (_isDone || _destroy)
                    {
                        success = false;
                    }
                }

                if (success)
                {
                    try
                    {
                        // _WriteStream(buffer, fileStream, finalPath);
                        fileStream.Close();
                        fileStream = null;
                        if (File.Exists(_finalPath))
                        {
                            File.Delete(_finalPath);
                        }
                        File.Move(tempPath, _finalPath);
                        _WriteMetadata(metaPath);
                        Complete(null);
                        // PrintDebug("download succeeded");
                        break;
                    }
                    catch (Exception exception)
                    {
                        // PrintError($"write exception: {exception}");
                        error   = $"write exception: {exception}";
                        success = false;
                    }
                }

                if (!Retry(++retry))
                {
                    if (fileStream != null)
                    {
                        fileStream.Close();
                        fileStream = null;
                    }
                    Complete(error ?? "unknown error");
                    PrintError($"[stop] download failed ({error})");
                    break;
                }
                Thread.Sleep(1000);
                PrintError($"[retry] ({_destroy}) download failed ({error})");
            }
            PrintDebug("download task thread exited");
        }