private void FromReaderToFile(StreamReader src, FileStream dest,
                                      ref DownloaderMetric metric, ref Stopwatch stopwatch, CancellationToken ct)
        {
            var buffer = new byte[32 * 1024];
            int bytesRead;

            while ((bytesRead = src.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                if (ct.IsCancellationRequested)
                {
                    dest.Flush(true);
                    dest.Close();
                    dest.Dispose();
                    return;
                }

                dest.Write(buffer, 0, bytesRead);
                metric.DownloadedBytes += bytesRead;
                metric.ElapsedTime      = stopwatch.Elapsed;
                OnDownloading?.Invoke(metric);
            }

            OnDownloadCompleted?.Invoke(metric);

            dest.Flush(true);
            dest.Close();
            dest.Dispose();
        }
        internal byte[] FromReaderToStream(StreamReader sr, Stream destinationStream,
                                           ref DownloadMetric metric, ref Stopwatch stopwatch, ref long?length, CancellationToken ct)
        {
            //int kb = metric.Speed > Globals.PageSize ? (int)metric.Speed : Globals.PageSize;
            int kb         = 1024 * 65;
            int toDownload = kb;
            var buffer     = new byte[toDownload];
            int bytesRead;

            while ((bytesRead = sr.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                // Poll on this property if you have to do
                // other cleanup before throwing.
                if (ct.IsCancellationRequested)
                {
                    // Clean up here, then...
                    destinationStream.SetLength(0);
                    destinationStream.Close();
                    if (destinationStream is FileStream)
                    {
                        var fs = destinationStream as FileStream;
                        if (File.Exists(fs.Name))
                        {
                            File.Delete(fs.Name);
                        }
                    }
                    ct.ThrowIfCancellationRequested();
                }

                destinationStream.Write(buffer, 0, bytesRead);
                metric.DownloadedBytes += bytesRead;
                metric.ElapsedTime      = stopwatch.Elapsed;
                OnDownloading?.Invoke(metric);

                length    -= bytesRead;
                toDownload = length >= kb ? kb : (int)length;
                buffer     = new byte[toDownload];
            }
            stopwatch.Stop();
            DownloadTrace.Invoke("Download finished!");
            DownloadTrace.Invoke("Returning results...");
            //DownloadCompleted?.Invoke(metric, destinationStream);
            //stopwatch.Reset();

            if (destinationStream is MemoryStream)
            {
                return(((MemoryStream)destinationStream).ToArray());
            }
            else
            {
                destinationStream.Flush();
                destinationStream.Close();
                destinationStream.Dispose();
                return(null);
            }
        }
Beispiel #3
0
        private Task StartSpeedControllerAsync()
        {
            return(Task.Factory.StartNew(async() =>
            {
                _logger.LogInformation($"任务 {Id} 速度控制器启动");
                bool @break = false;


                MemoryMappedFile mmf = MmfSignal
                    ? MemoryMappedFile.CreateFromFile(Id, FileMode.OpenOrCreate, null, 4,
                                                      MemoryMappedFileAccess.ReadWrite)
                    : null;

                using (var accessor = mmf?.CreateViewAccessor())
                {
                    accessor?.Write(0, false);
                    accessor?.Flush();

                    while (!@break)
                    {
                        Thread.Sleep(_speedControllerInterval);

                        switch (Status)
                        {
                        case Status.Running:
                            {
                                try
                                {
                                    var requests = _scheduler.Dequeue(Id, _dequeueBatchCount);
                                    foreach (var request in requests)
                                    {
                                        OnDownloading?.Invoke(request);
                                    }

                                    if (requests.Length > 0)
                                    {
                                        await _downloadService.EnqueueRequests(Id, requests);
                                    }
                                }
                                catch (Exception e)
                                {
                                    _logger.LogError($"速度控制器运转失败: {e}");
                                }

                                break;
                            }

                        case Status.Paused:
                            {
                                _logger.LogInformation($"任务 {Id} 速度控制器暂停");
                                break;
                            }

                        case Status.Exiting:
                        case Status.Exited:
                            {
                                @break = true;
                                break;
                            }
                        }

                        if (accessor != null && accessor.ReadBoolean(0))
                        {
                            Exit();
                            break;
                        }
                    }
                }

                _logger.LogInformation($"任务 {Id} 速度控制器退出");
            }));
        }
Beispiel #4
0
        public async Task DownloadAsync(string savePath)
        {
            _downloadTask = new Task(async() =>
            {
                using (var ms = new MemoryStream())
                {
                    try
                    {
                        var request = WebRequest.Create(this.Url) as HttpWebRequest;
                        if (request == null)
                        {
                            // todo
                            throw new Exception();
                        }

                        request.Timeout   = 30000;
                        request.UserAgent =
                            "ozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36";

                        var response = await request.GetResponseAsync().ConfigureAwait(false) as HttpWebResponse;
                        if (response == null)
                        {
                            // todo
                            throw new Exception();
                        }

                        using (var responseStream = response.GetResponseStream())
                        {
                            if (responseStream == null)
                            {
                                // todo
                                throw new Exception();
                            }

                            var fileSize = response.ContentLength;

                            OnStartDownloading?.Invoke(fileSize);

                            var bArr = new byte[1024];
                            var size = responseStream.Read(bArr, 0, bArr.Length);

                            long totalSize = 0;
                            long lastSize  = 0;
                            long speed     = 0;
                            _ = Task.Run(() =>
                            {
                                bool isFinished      = false;
                                OnFinishDownloading += () => { isFinished = true; };
                                const int interval   = 500;
                                const int ratio      = 1000 / interval;

                                while (!isFinished && !_cts.IsCancellationRequested)
                                {
                                    speed    = (totalSize - lastSize) * ratio;
                                    lastSize = totalSize;
                                    Thread.Sleep(interval);
                                }
                            });

                            while (size > 0)
                            {
                                if (_cts.IsCancellationRequested)
                                {
                                    Logger.Info(@"Download canceled.");
                                    return;
                                }

                                totalSize += size;
                                ms.Write(bArr, 0, size);
                                size = responseStream.Read(bArr, 0, (int)bArr.Length);
                                OnDownloading?.Invoke(fileSize, totalSize, speed);
                            }

                            var dir = new FileInfo(savePath).Directory;
                            if (!dir.Exists)
                            {
                                dir.Create();
                            }
                            using (var fs = new FileStream(savePath, FileMode.Append, FileAccess.Write,
                                                           FileShare.ReadWrite))
                            {
                                fs.Write(ms.GetBuffer(), 0, (int)ms.Length);
                            }

                            OnFinishDownloading?.Invoke();
                        }
                    }
                    catch (WebException ex)
                    {
                        if (ex.InnerException is SocketException)
                        {
                            Logger.Error(@"Connection error. Target URI: {0}", Url);
                            throw;
                        }

                        if (ex.Status == WebExceptionStatus.Timeout)
                        {
                            Logger.Error(@"Connection timed out. Target URI: {0}", Url);
                            throw;
                        }

                        throw;
                    }
                }
            });
            _downloadTask.Start();
            await Task.WhenAll(_downloadTask).ConfigureAwait(false);
        }
        public IEnumerator Start(bool resume = false)
        {
            Debug.LogFormat("[WebFileDownloader] Start :{0}", this.url);

            var headRequest = UnityWebRequest.Head(url);

            yield return(headRequest.SendWebRequest());

            //Debug.LogError("HeadRequest Error:" + headRequest.isNetworkError);
            if (headRequest.isNetworkError)
            {
                if (OnError != null)
                {
                    OnError(this);
                }
            }
            else
            {
                string len = headRequest.GetResponseHeader("Content-Length");

                Debug.Log("---------------------------获得长度:" + len);

                if (string.IsNullOrEmpty(len))
                {
                    //  Debug.Log(" 下载出错:" + len);
                    if (OnError != null)
                    {
                        OnError(this);
                    }
                }
                else
                {
                    var totalLength = long.Parse(len);
                    if (!Directory.Exists(filePath))
                    {
                        Directory.CreateDirectory(filePath);
                    }

                    string fileName     = Path.GetFileName(this.url);
                    string filePath2    = filePath + "/" + fileName;
                    string tempFilePath = filePath2 + EXTAINSION_NAME;
                    tempFilePath = tempFilePath.Replace("\\", "/");
                    filePath2    = filePath2.Replace("\\", "/");
                    string dir = Path.GetDirectoryName(filePath2);

                    if (!Directory.Exists(dir))
                    {
                        Directory.CreateDirectory(dir);
                    }

                    long  lastLen   = 0;
                    float _progress = 0;

                    using (FileStream stream = new FileStream(tempFilePath, FileMode.OpenOrCreate, FileAccess.Write))
                    {
                        var streamLength = stream.Length;

                        lastLen = streamLength;

                        if (!resume)
                        {
                            streamLength = 0;
                        }

                        if (streamLength < totalLength)
                        {
                            stream.Seek(streamLength, SeekOrigin.Current);
                        }


                        UnityWebRequest request = UnityWebRequest.Get(this.url);

                        request.SetRequestHeader("Range", "bytes=" + streamLength + "-" + totalLength);
                        request.SendWebRequest();
                        error = "";

                        int offset = 0;
                        while (true)
                        {
                            if (request.isNetworkError)
                            {
                                long code = request.responseCode;
                                //  Debug.LogFormat("[WebFileDownloader] Error:{0}", code);
                                error = request.error + ",responeseCode:" + request.responseCode;
                                break;
                            }

                            byte[] data   = request.downloadHandler.data;
                            int    length = data.Length - offset;
                            stream.Write(data, offset, length);
                            offset       += length;
                            streamLength += length;

                            _progress = (float)streamLength / (float)totalLength;

                            float val = (float)(streamLength + lastLen);

                            progress = val / totalLength;

                            //Debug.LogFormat("val:{0}, totalLength:{1} ,streamLength:{2} ,lastLen:{3} ===当前进度:{4}  实际progress:{5}",
                            //    val, totalLength, streamLength, lastLen, progress, _progress);

                            if (OnDownloading != null)
                            {
                                OnDownloading.Invoke(this);
                            }

                            if (_progress >= 1)
                            {
                                break;
                            }

                            yield return(0);
                        }

                        netDatas = request.downloadHandler.data;

                        headRequest.Dispose();
                        request.downloadHandler.Dispose();
                        request = null;
                        stream.Close();
                    }

                    if (string.IsNullOrEmpty(error))
                    {
                        if (File.Exists(tempFilePath))
                        {
                            ////Debug.Log("开始删除临时文件:"+ tempFilePath);
                            if (File.Exists(filePath2))
                            {
                                File.Delete(filePath2);
                            }

                            File.Move(tempFilePath, filePath2);
                            //Debug.LogFormat("存入本地文件地址:{0}", filePath2);
                        }

                        //Debug.Log(" 下载完成");

                        if (OnComplete != null)
                        {
                            OnComplete.Invoke(this);
                        }
                    }
                    else
                    {
                        //Debug.Log(" 下载出错");
                        if (OnError != null)
                        {
                            OnError(this);
                        }
                    }
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Http方式下载文件
        /// </summary>
        /// <param name="url">http地址</param>
        /// <param name="localfile">本地文件</param>
        /// <returns></returns>
        public bool Download(string url, string localfile)
        {
            Url          = url;
            SaveFilePath = localfile;

            long       startPosition = 0;    // 上次下载的文件起始位置
            FileStream writeStream   = null; // 写入本地文件流对象

            try
            {
                // 判断要下载的文件夹是否存在
                if (File.Exists(localfile))
                {
                    writeStream   = File.OpenWrite(localfile);           // 存在则打开要下载的文件
                    startPosition = writeStream.Length;                  // 获取已经下载的长度
                    writeStream.Seek(startPosition, SeekOrigin.Current); // 本地文件写入位置定位
                }
                else
                {
                    writeStream   = new FileStream(localfile, FileMode.Create);// 文件不保存创建一个文件
                    startPosition = 0;
                }


                HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(url);// 打开网络连接

                if (startPosition > 0)
                {
                    myRequest.AddRange((int)startPosition);// 设置Range值,与上面的writeStream.Seek用意相同,是为了定义远程文件读取位置
                }

                var myResponse = (HttpWebResponse)myRequest.GetResponse();
                FileTotalBytes = myResponse.ContentLength;

                FileDownloadedBytes = startPosition;

                Stream readStream = myRequest.GetResponse().GetResponseStream();  // 向服务器请求,获得服务器的回应数据流

                byte[] btArray     = new byte[512];                               // 定义一个字节数据,用来向readStream读取内容和向writeStream写入内容
                int    contentSize = readStream.Read(btArray, 0, btArray.Length); // 向远程文件读第一次

                IsRunning = true;

                while (contentSize > 0)// 如果读取长度大于零则继续读
                {
                    if (_isStop)
                    {
                        break;
                    }

                    writeStream.Write(btArray, 0, contentSize);// 写入本地文件
                    FileDownloadedBytes += contentSize;
                    OnDownloading?.Invoke(this);

                    contentSize = readStream.Read(btArray, 0, btArray.Length);// 继续向远程文件读取
                }

                //关闭流
                writeStream.Close();
                readStream.Close();

                IsDownloadSuccess = true;        //返回true下载成功
            }
            catch (Exception e)
            {
                Logger.Error(e, logger);

                if (writeStream != null)
                {
                    writeStream.Close();
                }

                IsDownloadSuccess = false;       //返回false下载失败
            }

            IsRunning = false;

            OnDownloadFinished?.Invoke(this);

            return(IsDownloadSuccess);
        }