Download the resumable upload function

Source: Internet
Author: User
Tags define local

The built-in download function of IE does not provide the resumable upload function. To implement the resumable upload function, you need to use several little-known HTTP Response Headers and request headers.
1. Two necessary response headers: Accept-Ranges and ETag
Each time the client submits a download request, the server must add these two response headers to ensure that the client and server recognize the download as resumable download:
Accept-Ranges: indicates that the download client is a resumable download that stores the start byte location and size of the file;
ETag: Unique Identifier of the file to be saved (I used the file name + the last modification time of the file to verify the file during the resume request );
Last-Modified: an optional response header that stores the Last modification time of the Server File for verification.

2. An important request header Range
Range: When downloading for the first time, the Range header is null. In this case, the server must add the Response Headers Accept-Ranges and ETag;
When the request is resumed, the value indicates the number of bytes received by the client, that is, the starting byte location of the download. The server reads data from the corresponding location and sends it to the client.

3. request headers for verification If-Range,
When the Response Headers include Accept-Ranges and ETag, the request headers are included in the resume request:
If-Range: The ETag value of the response header;
Unless-Modified-Since: the value of Last-Modified in the response header.
To ensure the consistency and correctness of the files on the client and the server, it is necessary to verify the files. To verify the files, you need to write the verification code by yourself and parse the values of the two request headers, compare the downloaded parts of the client with the files on the server. If the files do not match, the files are downloaded from the beginning. If the files match, the files are resumed.

Iv. Speed Limit
The program adds a speed limit to the traffic limit for permission control on the client.

5. Other considerations
For example, the file name is garbled, the space in the file name is changed to the plus sign, and the forced client displays the Download Dialog Box. For details, see the source code comment:

 

1
2/** // <summary>
3 // download an object. large objects, resumable data transfer, and speed restrictions are supported. Supports the Accept-Ranges, ETag, and request header Range.
4 // Accept-Ranges: Response Header, which indicates to the client that the process supports resumable download. The value of this process is bytes;
5 // ETag: The response header, used for initial (200) Responses to the client and recovery requests from the client,
6 // each file must have a unique ETag value (which may consist of the file name and the Last modified Date of the file ), this allows the client software to verify that the byte blocks they have downloaded are still up to date.
7 // Range: the starting position of the resume, that is, the number of bytes that have been downloaded to the client. The value is bytes = 1474560 -.
8 // In addition: After UrlEncode encoding, the space in the file name is converted to + (+ to % 2b), but the browser cannot understand the plus sign as a space, therefore, the space of the file downloaded in the browser becomes the plus sign;
9 // solution: After UrlEncode, replace "+" with "% 20" because the browser converts % 20 to a space.
10 /// </summary>
11 /// <param name = "httpContext"> HttpContext of the current request </param>
12 /// <param name = "filePath"> physical path of the downloaded file, including the path and file name </param>
13 // <param name = "speed"> download speed: the number of bytes allowed to be downloaded per second </param>
14 /// <returns> true: Download succeeded; false: Download failed </returns>
15 public static bool DownloadFile (HttpContext httpContext, string filePath, long speed)
16 {
17 bool ret = true;
18 try
19 {
20 -- Verification: HttpMethod, whether the requested file exists # region -- Verification: HttpMethod, whether the requested file exists
21 switch (httpContext. Request. HttpMethod. ToUpper ())
22 {// currently only the GET and HEAD methods are supported
23 case "GET ":
24 case "HEAD ":
25 break;
26 default:
27 HTTP context. Response. StatusCode = 501;
28 return false;
29}
30 if (! File. Exists (filePath ))
31 {
32 httpContext. Response. StatusCode = 404;
33 return false;
34}
35 # endregion
36
37. Define local variables # region defines local variables
38 long startBytes = 0;
39 int packSize = 1024*10; // multipart read, each 10 K bytes
40 string fileName = Path. GetFileName (filePath );
41 FileStream myFile = new FileStream (filePath, FileMode. Open, FileAccess. Read, FileShare. ReadWrite );
42 BinaryReader br = new BinaryReader (myFile );
43 long fileLength = myFile. Length;
44
45 int sleep = (int) Math. Ceiling (1000.0 * packSize/speed); // Number of milliseconds: The interval at which the next data block is read
46 string lastUpdateTiemStr = File. GetLastWriteTimeUtc (filePath). ToString ("r ");
47 string eTag = HttpUtility. UrlEncode (fileName, Encoding. UTF8) + lastUpdateTiemStr; // it is convenient to extract the request header when downloading;
48 # endregion
49
50 -- verify: whether the file is too large, whether it is resumed, and whether it has been modified after the last requested date ------------ # region -- verify: whether the file is too large, whether it is resumed, and whether it has been modified since the last requested date --------------
51 if (myFile. Length> Int32.MaxValue)
52 {// ------- the file is too large -------
53 httpContext. Response. StatusCode = 413; // The Request Entity is too large.
54 return false;
55}
56
57 if (httpContext. Request. Headers ["If-Range"]! = Null) // corresponding response header ETag: file name + last modification time of the file
58 {
59 // ---------- modified after the last requested date --------------
60 if (httpContext. Request. Headers ["If-Range"]. Replace ("\"","")! = ETag)
61 {// File Modified
62 httpContext. Response. StatusCode = 412; // preprocessing failed
63 return false;
64}
65}
66 # endregion
67
68 try
69 {
70 ------- add important response headers, parse request headers, related verifications ----------------- # region ------- add important response headers, parse request headers, related verifications -------------------
71 httpContext. Response. Clear ();
72 httpContext. Response. Buffer = false;
73 httpContext. Response. AddHeader ("Content-MD5", GetMD5Hash (myFile); // used to verify the file
74 httpContext. Response. AddHeader ("Accept-Ranges", "bytes"); // important: resumable upload is required.
75 httpContext. Response. AppendHeader ("ETag", "\" "+ eTag +" \ ""); // important: resumable upload is required.
76 httpContext. Response. AppendHeader ("Last-Modified", lastUpdateTiemStr); // write the Last modification date to the Response
77 httpContext. Response. ContentType = "application/octet-stream"; // MIME type: match any file type
78 httpContext. response. addHeader ("Content-Disposition", "attachment; filename =" + HttpUtility. urlEncode (fileName, Encoding. UTF8 ). replace ("+", "% 20 "));
79 httpContext. Response. AddHeader ("Content-Length", (fileLength-startBytes). ToString ());
80 httpContext. Response. AddHeader ("Connection", "Keep-Alive ");
81 httpContext. Response. ContentEncoding = Encoding. UTF8;
82 if (httpContext. Request. Headers ["Range"]! = Null)
83 {// ------ for a resume request, obtain the start position of the resume request, that is, the number of bytes that have been downloaded to the client ------
84 httpContext. Response. StatusCode = 206; // important: resumable upload is required, indicating local range Response. The default value is 200 during initial download.
85 string [] range = httpContext. request. headers ["Range"]. split (new char [] {'=', '-'}); // "bytes = 1474560 -"
86 startBytes = Convert. ToInt64 (range [1]); // The number of bytes that have been downloaded, that is, the start position of this download.
87 if (startBytes <0 | startBytes> = fileLength)
88 {// invalid start position
89 return false;
90}
91}
92 if (startBytes> 0)
93 {// ------ In the case of a resumable data transfer request, the client is notified of the number of start bytes and the total length, so that the client can append the data to the startBytes location ----------
94 httpContext. response. addHeader ("Content-Range", string. format ("bytes {0}-{1}/{2}", startBytes, fileLength-1, fileLength ));
95}
96 # endregion
97
98 ------- send data blocks to the client ----------------- # region ------- send data blocks to the client -------------------
99 br. BaseStream. Seek (startBytes, SeekOrigin. Begin );
100 int maxCount = (int) Math. Ceiling (fileLength-startBytes + 0.0)/packSize); // multipart download, number of parts that can be divided
101 for (int I = 0; I <maxCount & httpContext. Response. IsClientConnected; I ++)
102 {// The client suspends the connection
103 httpContext. Response. BinaryWrite (br. ReadBytes (packSize ));
104 httpContext. Response. Flush ();
105 if (sleep> 1) Thread. Sleep (sleep );
106}
107 # endregion
108}
109 catch
110 {
111 ret = false;
112}
113 finally
114 {
115 br. Close ();
116 myFile. Close ();
117}
118}
119 catch
120 {
121 ret = false;
122}
123 return ret;
124}

 

 

 

HttpContext. Response. Flush (); // This sentence can be omitted...

Call Convention:

Page. Response. Clear ();

Bool success = ResponseFile (Page. Request,

Page. Response, "filename", @ "C: \ download. date", 1024000 );

If (! Success) Response. Write ("An error occurred while downloading the file! ");

Page. Response. End ();

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.