亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

基于HTTP的斷點傳輸

Original 2016-11-09 15:48:29 670
abstract:最近項目需要做一個類似于迅雷的文件下載功能,這類需求可能比較常見,希望可以幫助到有需要的同學(xué)要求:1.支持斷點傳輸2. 多文件同時下載3. 由于是客戶內(nèi)部試用,服務(wù)器只支持HTTP文件下載不支持FTP文件(并沒有用戶權(quán)限的要求)由于根據(jù)服務(wù)器傳來的Json字符串解析后進行下載,首先構(gòu)建Json對象,推薦一個庫Newtonsoft.Jsonpublic class Downloa

最近項目需要做一個類似于迅雷的文件下載功能,這類需求可能比較常見,希望可以幫助到有需要的同學(xué)

要求:

1.支持斷點傳輸

2. 多文件同時下載

3. 由于是客戶內(nèi)部試用,服務(wù)器只支持HTTP文件下載不支持FTP文件(并沒有用戶權(quán)限的要求)

由于根據(jù)服務(wù)器傳來的Json字符串解析后進行下載,首先構(gòu)建Json對象,推薦一個庫Newtonsoft.Json

public class DownloadFile
    {
        [JsonProperty("police_num")]
        public string PoliceNumber { get; set; }
        [JsonProperty("equipment_num")]
        public string EquipmentNumber { get; set; }
        [JsonProperty("upload_date")]
        public DateTime UploadDateTime { get; set; }
        [JsonProperty("type")]
        public string FileType { get; set; }
        [JsonProperty("file_name")]
        public string FileName { get; set; }
        [JsonProperty("file_path")]
        public string FilePath { get; set; }
    }

JsonProperty不區(qū)分大小寫

public class DownloadTask : ObservableObject
    {
        /// <summary>
        /// </summary>
        public static readonly int BufferSize = 1024;
        /// <summary>
        ///     一次請求大小,每次請求100kb
        /// </summary>
        public static long Step = 1024*100;
        private int _process;
        /// <summary>
        ///     下載文件參數(shù)
        /// </summary>
        public DownloadFile DownloadFile { get; set; }
        /// <summary>
        ///     下載文件狀態(tài)
        /// </summary>
        public SegmentState SegmentState { get; set; }
        /// <summary>
        ///     默認存儲路徑
        /// </summary>
        public string DefaultDirectory { get; set; }
        /// <summary>
        ///     當(dāng)前進度
        /// </summary>
        public long CurrentSize { get; set; }
        /// <summary>
        ///     文件流對象,用于生成文件
        /// </summary>
        public FileStream FileStream { get; set; }
        /// <summary>
        ///     下載起始位置
        /// </summary>
        public long RangeFrom { get; set; }
        /// <summary>
        ///     總大小
        /// </summary>
        public long TotalSize { get; set; }
        /// <summary>
        ///     鏈接地址
        /// </summary>
        public string Url { get; set; }
        /// <summary>
        ///     界面顯示進度
        /// </summary>
        public int Process
        {
            get { return _process; }
            set
            {
                _process = value;
                RaisePropertyChanged("Process");
            }
        }
    }

下載服務(wù)類,DownloaderService.cs,功能包括啟動下載,暫停,針對文件是否存在進行初始化,獲取文件大小方便界面顯示

public class DownloaderService
    {
        public void OnStart(DownloadTask downloadTask)
        {
            if (!InitService(downloadTask)) return;
            var downloadThread = new Thread(BeginDownloadFile) { IsBackground = true };
            downloadThread.Start(downloadTask);
        }
        public void OnStop(DownloadTask downloadTask)
        {
            downloadTask.SegmentState = SegmentState.Paused;
        }
        private bool InitService(DownloadTask downloadTask)
        {
            try
            {
                if (string.IsNullOrEmpty(downloadTask.Url))
                {
                    return false;
                }
                downloadTask.DownloadFile.FileName = downloadTask.Url.Substring(downloadTask.Url.LastIndexOf('/') + 1);
                var fullName = Path.Combine(downloadTask.DefaultDirectory, downloadTask.DownloadFile.FileName);
                if (File.Exists(fullName))
                {
                    if (downloadTask.TotalSize == 0)
                    {
                        GetTotalSize(downloadTask);
                    }
                    if (downloadTask.CurrentSize == downloadTask.TotalSize)
                    {
                        if (MessageBox.Show("文件已經(jīng)存在是否覆蓋此文件", "TCL", MessageBoxButton.YesNo, MessageBoxImage.Information) !=
                        MessageBoxResult.Yes)
                            return false;
                        File.Delete(fullName);
                        downloadTask.CurrentSize = 0;
                    }
                    downloadTask.FileStream = new FileStream(fullName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    downloadTask.SegmentState = SegmentState.Downloading;
                    return true;
                }
                downloadTask.SegmentState = SegmentState.Downloading;
                downloadTask.FileStream = new FileStream(fullName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                return true;
            }
            catch (Exception ex)
            {
                LogLightConsole.WriteLog(ex.ToString(), EunmMsgType.Error);
                return false;
            }
        }
        private void BeginDownloadFile(object obj)
        {
            try
            {
                var downloadTask = (DownloadTask)obj;
                while (true)
                {
                    if (downloadTask.SegmentState == SegmentState.Paused)
                    {
                        downloadTask.FileStream.Close();
                        break;
                    }
                    //從0計數(shù),需要減一
                    var from = downloadTask.CurrentSize;
                    if (from < 0)
                    {
                        from = 0;
                    }
                    var to = downloadTask.CurrentSize + DownloadTask.Step - 1;
                    if (to >= downloadTask.TotalSize && downloadTask.TotalSize > 0)
                    {
                        to = downloadTask.TotalSize - 1;
                    }
                    if (downloadTask.TotalSize == 0)
                    {
                        GetTotalSize(downloadTask);
                    }
                    if (from >= downloadTask.TotalSize || downloadTask.CurrentSize >= downloadTask.TotalSize)
                    {
                        downloadTask.SegmentState = SegmentState.Finished;
                        downloadTask.FileStream.Close();
                        downloadTask.Process = 100;
                        return;
                    }
                    var request = (HttpWebRequest)WebRequest.Create(downloadTask.Url);
                    //request.Method = "GET";            
                    request.AddRange("bytes", from, to);
                    request.Timeout = 1000 * 20;
                    var response = (HttpWebResponse)request.GetResponse();
                    var buffer = new byte[1024];
                    using (var stream = response.GetResponseStream())
                    {
                        if (stream != null)
                        {
                            var size = stream.Read(buffer, 0, buffer.Length);
                            while (size > 0)
                            {
                                //只將讀出的字節(jié)寫入文件
                                downloadTask.FileStream.Write(buffer, 0, size);
                                downloadTask.CurrentSize += size;
                                size = stream.Read(buffer, 0, buffer.Length);
                                downloadTask.Process = (int)(downloadTask.CurrentSize * 100 / downloadTask.TotalSize);
                                downloadTask.FileStream.Flush();
                            }
                        }
                        //如果返回的response頭中Content-Range值為空,說明服務(wù)器不支持Range屬性,不支持斷點續(xù)傳,返回的是所有數(shù)據(jù)
                        if (response.Headers["Content-Range"] == null)
                        {
                            downloadTask.SegmentState = SegmentState.Finished;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogLightConsole.WriteLog("BeginDownloadFile" + ex, EunmMsgType.Error);
            }
        }
        /// <summary>
        ///     獲取文件總大小
        /// </summary>
        public void GetTotalSize(DownloadTask downloadTask)
        {
            var request = (HttpWebRequest)WebRequest.Create(downloadTask.Url);
            //request.Method = "POST";
            //request.Headers.Add("charset:" + "utf-8");
            request.Timeout = 1000 * 20;
            var response = (HttpWebResponse)request.GetResponse();
            downloadTask.TotalSize = response.ContentLength;
        }
    }

HTTP 1.1版本本身已經(jīng)擴展了斷點傳輸功能,但是這需要服務(wù)器同時也支持,這只是提供了一個簡單的例子,具體的針對數(shù)據(jù)上下文以及成功失敗的callback函數(shù),就是做一下委托封裝用就好,謝謝大家支持!

response.Headers["Content-Range"] == null 說明服務(wù)器不支持斷點傳輸


Release Notes

Popular Entries