HTTP-based breakpoint transmission and HTTP breakpoint Transmission
A file downloading function similar to thunder is required in recent projects. This type of requirement may be common and may be helpful to those in need.
Requirements:
1. Support for breakpoint Transmission
2. Simultaneous download of multiple files
3. Because it is an internal trial by the customer, the server only supports downloading HTTP files and does not support FTP files (there is no requirement for user permissions)
Since the server parses the Json string and downloads it, we first construct a Json object. We recommend a library 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 is case insensitive
Public class DownloadTask: ObservableObject {// <summary> /// </summary> public static readonly int BufferSize = 1024; // <summary> // the size of one request, each request is 100kb // </summary> public static long Step = 1024*100; private int _ process; /// <summary> /// download file parameters /// </summary> public DownloadFile {get; set ;} /// <summary> /// download file status /// </summary> public SegmentState {get; set ;} /// <summary> /// default storage path /// </summary> public string DefaultDirectory {get; set ;} /// <summary> /// current progress /// </summary> public long CurrentSize {get; set ;}/// <summary> /// file stream object, used to generate a file // </summary> public FileStream {get; set ;} /// <summary> /// download start position /// </summary> public long RangeFrom {get; set ;} /// <summary> /// total size /// </summary> public long TotalSize {get; set ;} /// <summary> /// link address /// </summary> public string Url {get; set ;} /// <summary> /// progress displayed on the page /// </summary> public int Process {get {return _ process;} set {_ process = value; raisePropertyChanged ("Process ");}}}
Download service class: DownloaderService. cs. This function can be used to start and pause the download. It initializes the existence of the file to facilitate the display of the file size.
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. fileN Ame = 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 ("whether to overwrite this file already exists", "TCL", MessageBoxButton. yesNo, MessageBoxI Mage. 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. rea DWrite); 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;} // count from 0. A var from = downloadTask is required. 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. clos E (); 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) {// write only the read bytes to the file 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 () ;}// if the returned Content-Range value in the response header is null, the server does not support the Range attribute and resumable data transfer, the returned data is all if (response. headers ["Content-Range"] = null) {downloadTask. segmentState = SegmentState. finished ;}}} catch (Exception ex) {LogLightConsole. writeLog ("BeginDownloadFile" + ex, EunmMsgType. error) ;}//< summary> /// obtain the total file size /// </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 has already extended the breakpoint transmission function, but this requires the server to support it at the same time. This is just a simple example. It is specific to the data context and the callback function for successful failures, just use the delegated encapsulation. If you have any questions, please trust me. Thank you for your support!
Response. Headers ["Content-Range"] = null indicates that the server does not support breakpoint transmission.