IE's own download function does not have the ability to continue the breakpoint, in order to achieve the continuation of the breakpoint, you need to use the HTTP protocol, a few little-known response headers and request headers.
I. Two required response heads Accept-ranges, ETag
Each time a client submits a download request, both response headers are added to the server to ensure that the client and server recognize this download as a download that can be resumed on a breakpoint:
Accept-ranges: Tell the download client this is a download that can resume, storing the start byte location of this download, the size of the file bytes;
ETAG: The unique identification of the saved file (the file name I used and the last modification time of the files to verify the file when the request was continued);
Last-modified: Optional response header to store the last modified time of the server file for verification
Two. One important request header range
Range: When first downloaded, the range header is null, and the response header accept-ranges, ETag must be added to the server's response header;
When a request is continued, its value indicates the number of bytes that the client has received, that is, the start byte position of the download, and the server reads the data from the corresponding location to the client based on this value.
Three. Request headers for authentication if-range,
When a accept-ranges, ETag is included in the response header, the request headers are included when the request is resumed:
If-range: The value corresponding to the etag of the response head;
Unless-modified-since: The value corresponding to the response header last-modified.
The continuation of the request, in order to ensure that the client and server file consistency and correctness, it is necessary to verify the file, verify the need to write their own verification code, based on the resolution of the two request header values, the client has downloaded the portion of the server and the file to compare, if not match, then from the beginning to download, if it matches, Then the breakpoint continues to pass.
Four. Speed limit
A speed limit is added to the program, which limits the traffic to the client for permission control.
Five. Other precautions
such as: file name garbled problem, file name hollow lattice variable Plus, force client Display Download dialog box, see Source Comments:
Java code
- /**////<summary>
- Download files, support large files, continuous transmission, speed limit. The response head accept-ranges, ETAG, and request header range are continuously transmitted.
- Accept-ranges: The response header, which indicates to the client that this process supports recoverable downloads. Implement Background Intelligent Transfer Service (BITS) with a value of: bytes;
- ETag: The response header, the initial (200) response to the client, and the recovery request from the client,
- Each file must be provided with a unique ETag value (which can consist of the file name and the date the file was last modified), which enables the client software to verify that the block of bytes they have downloaded is still up to date.
- Range: The starting position of the continuation, that is, the number of bytes downloaded to the client, such as: bytes=1474560-.
- In addition: UrlEncode encoding will be the file name in the space conversion + (+ conversion to%2b), but the browser is not able to understand the plus is a space, so in the browser to download the file, the space becomes a plus;
- Workaround: After UrlEncode, replace "+" with "%20" because the browser converts%20 to a space
- </summary>
- <param name= "HttpContext" > Current request httpcontext</param>
- <param name= "FilePath" > The physical path of the downloaded file, including the path, file name </param>
- <param name= "Speed" > Download rate: bytes per second allowed to download </param>
- <returns>true download succeeded, false download failed </returns>
- Public static BOOL DownloadFile (HttpContext HttpContext, String FilePath, long speed)
- {
- BOOL ret = true;
- Try
- {
- #region--Verify: HttpMethod, the requested file exists
- switch (HttpContext.Request.HttpMethod.ToUpper ())
- { //currently only the get and head methods are supported
- case "GET":
- case "HEAD":
- Break ;
- Default:
- HttpContext.Response.StatusCode = 501;
- return false;
- }
- if (! File.exists (FilePath))
- {
- HttpContext.Response.StatusCode = 404;
- return false;
- }
- #endregion
- #region Defining Local Variables
- long startbytes = 0;
- int packsize = 1024x768 * 10; //block read, 10K bytes per block
- String fileName = Path.getfilename (FilePath);
- FileStream myFile = new FileStream (FilePath, FileMode.Open, FileAccess.Read, fileshare.readwrite);
- BinaryReader br = new BinaryReader (MyFile);
- long filelength = myfile.length;
- int sleep = (int) math.ceiling (1000.0 * packsize/speed); Number of milliseconds: the time interval to read the next block of data
- String lastupdatetiemstr = FILE.GETLASTWRITETIMEUTC (FilePath). ToString ("R");
- String eTag = Httputility.urlencode (FileName, Encoding.UTF8) + lastupdatetiemstr; //Easy to retrieve the request header when downloading;
- #endregion
- #region-Verify: Whether the file is too large, whether it is a continuation, and whether it was repaired after the last requested date
- if (Myfile.length > Int32.MaxValue)
- {//-------file is too large-------
- HttpContext.Response.StatusCode = 413; Request entity too large
- return false;
- }
- if (httpcontext.request.headers["If-range"]! = null)//corresponding response header etag: filename + file Last modified time
- {
- //----------has been modified since the last requested date--------------
- if (httpcontext.request.headers["If-range"]. Replace ("\" ", " ")! = ETag)
- {//file modified
- HttpContext.Response.StatusCode = 412; Preprocessing failed
- return false;
- }
- }
- #endregion
- Try
- {
- #region-------Add Critical response headers, parse request headers, and related validations-------------------
- HttpContext.Response.Clear ();
- HttpContext.Response.Buffer = false;
- HttpContext.Response.AddHeader ("Content-md5", Getmd5hash (MyFile)); Used to validate files
- HttpContext.Response.AddHeader ("Accept-ranges", "bytes"); IMPORTANT: Continued transmission must be
- HttpContext.Response.AppendHeader ("ETag", "\" "+ ETag + " \ "); IMPORTANT: Continued transmission must be
- HttpContext.Response.AppendHeader ("last-modified", lastupdatetiemstr); Write the last modified date to the response
- HttpContext.Response.ContentType = "Application/octet-stream"; MIME type: Matches any file type
- HttpContext.Response.AddHeader ("content-disposition", "attachment;filename=" + httputility.urlencode ( FileName, Encoding.UTF8). Replace ("+", "%20"));
- HttpContext.Response.AddHeader ("Content-length", (filelength-startbytes). ToString ());
- HttpContext.Response.AddHeader ("Connection", "keep-alive");
- httpContext.Response.ContentEncoding = Encoding.UTF8;
- if (httpcontext.request.headers["Range"]! = null)
- {//------If it is a continuation request, gets the starting position of the continuation, that is, the number of bytes that have been downloaded to the client------
- HttpContext.Response.StatusCode = 206; Important: The continuation must indicate a local range response. Initial download defaults to
- string[] Range = httpcontext.request.headers["range"]. Split (new char[] { ' = ', '-'}); "bytes=1474560-"
- Startbytes = Convert.toint64 (range[1]); The number of bytes that have been downloaded, that is, where the download started
- if (Startbytes < 0 | | startbytes >= filelength)
- {//invalid start position
- return false;
- }
- }
- if (Startbytes > 0)
- {//------If it is a continuation request, it tells the client the starting byte number, the total length, so that the client appends the continuation data to the Startbytes location----------
- HttpContext.Response.AddHeader ("Content-range", String. Format ("bytes {0}-{1}/{2}", Startbytes, Filelength- 1, filelength));
- }
- #endregion
- #region-------Send a block of data to the client-------------------
- Br. Basestream.seek (Startbytes, Seekorigin.begin);
- int maxCount = (int) math.ceiling ((filelength-startbytes + 0.0)/packsize); Block download, the number of blocks that the remainder can be divided into
- For (int i = 0; i < maxCount && httpContext.Response.IsClientConnected; i++)
- {//client interrupts connection, pause
- HttpContext.Response.BinaryWrite (Br. Readbytes (packsize));
- HttpContext.Response.Flush ();
- if (Sleep > 1) thread.sleep (sleep);
- }
- #endregion
- }
- Catch
- {
- ret = false;
- }
- finally
- {
- Br. Close ();
- Myfile.close ();
- }
- }
- Catch
- {
- ret = false;
- }
- return ret;
- }
Transferred from: http://www.cnblogs.com/gjahead/archive/2007/06/18/787654.html