An introduction
The most of the breakpoint continuation search is the downloaded breakpoint continuation, which involves the range and Content-range headers of HTTP protocol 1.1.
Here's a simple introduction.
The so-called breakpoint continuation, that is, the file has been downloaded from the place to continue to download. In the previous version of the HTTP protocol is not support breakpoints, http/1.1 began to support. The Range and Content-range entity headers are only used when a general breakpoint is downloaded.
Range
For the request header, specify the position of the first byte and the position of the last byte, in general format:
Range: (Unit=first byte pos)-[last byte POS]
Content-range
For the response header, which specifies the insertion position of a part of the entire entity, he also indicates the length of the entire entity. When the server returns a partial response to the customer, it must describe the extent of the response coverage and the entire length of the entity. General format:
Content-range:bytes (unit first byte pos) –[last byte pos]/[entity legth]
Request to download the entire file:
- Get/test.rar http/1.1
- Connection:close
- host:116.1.219.219
- range:bytes=0-801//General request to download the entire file is bytes=0-or without this header
General Normal response
- http/1.1 OK
- content-length:801
- Content-type:application/octet-stream
- Content-range:bytes 0-800/801//801: Total File size
And today is to say that the upload of the breakpoint continued to use the Content-range head
Upload the continuation of the principle and download the same as the continuation of the transmission.
is to upload the file before uploading it. Server-side receive merge, even if the upload is broken. The next upload will still merge files from the existing bytes of the file on the server side. The final upload is complete.
Two implementations
Server-side
The service side is WEBAPI implementation. or Mvc,webform.
The principle of the service side is to receive the upload data stream. Save the file. If this file already exists. is to merge existing files.
The file name here is the data sent by the client.
The file name is the MD5 of the file, guaranteeing the uniqueness of the file.
[Httpget]public httpresponsemessage Getresumfile () {//is used to obtain whether the current file is a continuation. And the number of bytes to be resumed at the start point. var md5str = httpcontext.current.request.querystring["Md5str"];var Savefilepath = HttpContext.Current.Server.MapPath ("~/images/") + md5str;if (System.IO.File.Exists (Savefilepath)) {var fs = System.IO.File.OpenWrite (Savefilepath); var Fslength = fs. Length.tostring (); fs. Close (); return new Httpresponsemessage {Content = new stringcontent (fslength, System.Text.Encoding.UTF8, "Text/plain") };} return new Httpresponsemessage (Httpstatuscode.ok);} [HttpPost] public httpresponsemessage rsume () {var file = HttpContext.Current.Request.InputStre Am var filename = httpcontext.current.request.querystring["filename"]; This. SaveAs (HttpContext.Current.Server.MapPath ("~/images/") + filename, file); HttpContext.Current.Response.StatusCode = 200; For compatibility with IE's "done" event we need to return a result as well as setting the Context.response return new Httpresponsemessage (Httpstatuscode.ok); } private void SaveAs (String Savefilepath,system.io.stream Stream) {long lstartpos = 0; int startposition = 0; int endposition = 0; var contentrange = httpcontext.current.request.headers["Content-range"]; Bytes 10000-19999/1157632 if (!string. IsNullOrEmpty (Contentrange)) {Contentrange = Contentrange.replace ("bytes", ""). Trim (); Contentrange = contentrange.substring (0, Contentrange.indexof ("/")); string[] ranges = contentrange.split ('-'); startposition = Int. Parse (Ranges[0]); endposition = Int. Parse (Ranges[1]); } System.IO.FileStream FS; if (System.IO.File.Exists (Savefilepath)) {fs = System.IO.File.OpenWrite (Savefilepath); Lstartpos = fs. Length; } else {fs = new System.IO.FileStream (Savefilepath, System.IO.FileMode.Create); Lstartpos = 0; } if (Lstartpos > Endposition) {fs. Close (); Return } else if (Lstartpos < startposition) {lstartpos = startposition; } else if (Lstartpos > StartPosition && lstartpos < endposition) {Lsta Rtpos = startposition; } fs. Seek (Lstartpos, System.IO.SeekOrigin.Current); byte[] nbytes = new byte[512]; int nreadsize = 0; Nreadsize = stream. Read (nbytes, 0, 512); while (Nreadsize > 0) {fs. Write (nbytes, 0, nreadsize); Nreadsize = stream. Read (nbytes, 0, 512); } fs. Close (); }
Client
The client here is WinForm, the function is to select files immediately after uploading. If the halfway network, breakpoints and other factors are not successful.
You can select this file to upload again. The server merges the previously transferred file bytes. Implement a breakpoint to continue the transmission.
private void Btnselectfile_click (object sender, EventArgs e) {OpenFileDialog OpenFileDialog = new Openf Iledialog (); Openfiledialog.initialdirectory = "c:\\"; Openfiledialog.restoredirectory = true; Openfiledialog.filterindex = 1; if (openfiledialog.showdialog () = = DialogResult.OK) {var fName = Openfiledialog.filename; FileStream fstream = new FileStream (FName, FileMode.Open, FileAccess.Read); var mdfstr = GetStreamMd5 (fstream); Fstream.close (); var startpoint = Isresume (Mdfstr, Path.getextension (fName)); MessageBox.Show (UploadFile (fName, URL, startpoint,mdfstr)); }}////<summary>///To get the next start node for continuation and continuation based on filename///</summary>//<param name = "Md5str" ></param>//<param name= "Fileextname" ></param>//<returns></returns > private int Isresume (string md5str, String fileextname) {System.Net.WebClient webclientobj = new System.Net.WebClient (); var url = "Http://localhost:13174/api/file/GetResumFile?md5str=" +md5str+fileextname; byte[] byremoteinfo = webclientobj.downloaddata (URL); string result = System.Text.Encoding.UTF8.GetString (byremoteinfo); if (string. IsNullOrEmpty (Result) {return 0; } return Convert.ToInt32 (result); } #region///<summary>///Upload file (auto-Split)///</summary>//<param name= "f Ilepath "> File full path name to be uploaded </param>//<param name=" Hosturl "> Server address </param>//<param Nam E= "ByteCount" > Split byte size </param>//<param name= "cruuent" > Current byte pointer </param>//< Returns> successfully returned "", Failure returns error message </returns> public string UploadFile (string FilePath, String hosTurl, int byteCount, long cruuent, string mdfstr) {string tmpurl = Hosturl; ByteCount = ByteCount * 1024; System.Net.WebClient webclientobj = new System.Net.WebClient (); FileStream fstream = new FileStream (FilePath, FileMode.Open, FileAccess.Read); BinaryReader breader = new BinaryReader (fstream); Long length = fstream.length; String sMsg = "Upload succeeded"; String fileName = filepath.substring (filepath.lastindexof (' \ \ ') + 1); try {#region continue processing byte[] data; if (Cruuent > 0) {fstream.seek (cruuent, seekorigin.current); } #endregion #region split file upload for (; cruuent <= length; cruuent = Cruuent + ByteCount) {if (cruuent + byteCount > Length) { data = new BytE[convert.toint64 ((length-cruuent))]; Breader.read (data, 0, Convert.ToInt32 ((length-cruuent))); } else {data = new Byte[bytecount]; Breader.read (data, 0, ByteCount); } try {//*** bytes 21010-47021/470 WebClientObj.Headers.Remove (Httprequestheader.contentrange); WEBCLIENTOBJ.HEADERS.ADD (Httprequestheader.contentrange, "bytes" + cruuent + "-" + (Cruuent + byteCount) + "/" + fstream. Length); Hosturl = Tmpurl + "? filename=" + mdfstr + path.getextension (filename); byte[] Byremoteinfo = Webclientobj.uploaddata (Hosturl, "POST", data); String sremoteinfo = System.Text.Encoding.Default.GetString (Byremoteinfo); Gets the return information if (Sremoteinfo.trim () = "") { SMSG = Sremoteinfo; Break }} catch (Exception ex) {SMSG = ex. ToString (); Break } #endregion}} catch (Exception ex) {SMs g = SMsg + ex. ToString (); } try {breader.close (); Fstream.close (); } catch (Exception exmsg) {sMsg = Exmsg.tostring (); } GC. Collect (); return SMSG; } public static string GetStreamMd5 (Stream stream) {var omd5hasher = new MD5CryptoServiceProvider (); byte[] Arrbythashval UE = Omd5hasher.computehash (stream); A string consisting of hexadecimal pairs separated by hyphens, where each pair of tablesThe corresponding element in value, such as "f-2c-4a" string strhashdata = Bitconverter.tostring (Arrbythashvalue); Replace-strhashdata = Strhashdata.replace ("-", "" "); string strresult = Strhashdata; return strresult; }
. NET implementation upload file segmentation, breakpoint continued upload file