Supports resumable download of large files (ZT) in ASP. NET)

Source: Internet
Author: User

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:

Java code
  1. /** // <Summary>
  2. /// Download an object. large objects, resumable data transfer, and speed restrictions are supported. Supports the Accept-Ranges, ETag, and request header Range.
  3. /// Accept-Ranges: Response Header, which indicates to the client that the process supports resumable download. The value of this process is bytes;
  4. /// ETag: The response header, used for initial (200) Responses to the client and recovery requests from the client,
  5. /// Each file must have a unique ETag value (which can be composed 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.
  6. /// 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 -.
  7. /// 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;
  8. /// Solution: After UrlEncode, replace "+" with "% 20" because the browser converts % 20 to a space.
  9. /// </Summary>
  10. /// <Param name = "httpContext"> HttpContext of the current request </param>
  11. /// <Param name = "filePath"> physical path of the downloaded file, including the path and file name </param>
  12. /// <Param name = "speed"> download speed: the number of bytes allowed to be downloaded per second </param>
  13. /// <Returns> true: Download succeeded; false: Download failed </returns>
  14. Public static bool DownloadFile (HttpContext httpContext, string filePath, long speed)
  15. {
  16. Bool ret = true;
  17. Try
  18. {
  19. # Region -- verify: HttpMethod: whether the requested file exists
  20. Switch (httpContext. Request. HttpMethod. ToUpper ())
  21. {// Currently only the GET and HEAD methods are supported
  22. Case "GET ":
  23. Case "HEAD ":
  24. Break;
  25. Default:
  26. HttpContext. Response. StatusCode = 501;
  27. Return false;
  28. }
  29. If (! File. Exists (filePath ))
  30. {
  31. HttpContext. Response. StatusCode = 404;
  32. Return false;
  33. }
  34. # Endregion
  35. # Region defines local variables
  36. Long startBytes = 0;
  37. Int packSize = 1024*10; // multipart read, each 10 K bytes
  38. String fileName = Path. GetFileName (filePath );
  39. FileStream myFile = new FileStream (filePath, FileMode. Open, FileAccess. Read, FileShare. ReadWrite );
  40. BinaryReader br = new BinaryReader (myFile );
  41. Long fileLength = myFile. Length;
  42. Int sleep = (int) Math. Ceiling (1000.0 * packSize/speed); // Number of milliseconds: The interval at which the next data block is read
  43. String lastUpdateTiemStr = File. GetLastWriteTimeUtc (filePath). ToString ("r ");
  44. String eTag = HttpUtility. UrlEncode (fileName, Encoding. UTF8) + lastUpdateTiemStr; // it is convenient to extract the request header when downloading;
  45. # Endregion
  46. # Region -- verify whether the file is too large, whether it is resumed, and whether it is repaired after the last requested date
  47. If (myFile. Length> Int32.MaxValue)
  48. {// ------- The file is too large -------
  49. HttpContext. Response. StatusCode = 413; // The Request Entity is too large.
  50. Return false;
  51. }
  52. If (httpContext. Request. Headers ["If-Range"]! = Null) // corresponding response header ETag: file name + last modification time of the file
  53. {
  54. // ---------- Modified after the last requested date --------------
  55. If (httpContext. Request. Headers ["If-Range"]. Replace ("\"","")! = ETag)
  56. {// File Modified
  57. HttpContext. Response. StatusCode = 412; // preprocessing failed
  58. Return false;
  59. }
  60. }
  61. # Endregion
  62. Try
  63. {
  64. # Region ------- add important response headers, parse request headers, and perform related verification -------------------
  65. HttpContext. Response. Clear ();
  66. HttpContext. Response. Buffer = false;
  67. HttpContext. Response. AddHeader ("Content-MD5", GetMD5Hash (myFile); // used to verify the file
  68. HttpContext. Response. AddHeader ("Accept-Ranges", "bytes"); // important: resumable upload is required.
  69. HttpContext. Response. AppendHeader ("ETag", "\" "+ eTag +" \ ""); // important: resumable upload is required.
  70. HttpContext. Response. AppendHeader ("Last-Modified", lastUpdateTiemStr); // write the Last Modified date to the Response
  71. HttpContext. Response. ContentType = "application/octet-stream"; // MIME type: match any file type
  72. HttpContext. response. addHeader ("Content-Disposition", "attachment; filename =" + HttpUtility. urlEncode (fileName, Encoding. UTF8 ). replace ("+", "% 20 "));
  73. HttpContext. Response. AddHeader ("Content-Length", (fileLength-startBytes). ToString ());
  74. HttpContext. Response. AddHeader ("Connection", "Keep-Alive ");
  75. HttpContext. Response. ContentEncoding = Encoding. UTF8;
  76. If (httpContext. Request. Headers ["Range"]! = Null)
  77. {// ------ 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 ------
  78. HttpContext. Response. StatusCode = 206; // important: resumable upload is required, indicating local range Response. The default value is 200 during initial download.
  79. String [] range = httpContext. request. headers ["Range"]. split (new char [] {'=', '-'}); // "bytes = 1474560 -"
  80. StartBytes = Convert. ToInt64 (range [1]); // The number of bytes that have been downloaded, that is, the start position of this download.
  81. If (startBytes <0 | startBytes> = fileLength)
  82. {// Invalid start position
  83. Return false;
  84. }
  85. }
  86. If (startBytes> 0)
  87. {// ------ 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 ----------
  88. HttpContext. response. addHeader ("Content-Range", string. format ("bytes {0}-{1}/{2}", startBytes, fileLength-1, fileLength ));
  89. }
  90. # Endregion
  91. # Region ------- send a data block ------------------- to the client -------------------
  92. Br. BaseStream. Seek (startBytes, SeekOrigin. Begin );
  93. Int maxCount = (int) Math. Ceiling (fileLength-startBytes + 0.0)/packSize); // The number of parts that can be divided
  94. For (int I = 0; I <maxCount & httpContext. Response. IsClientConnected; I ++)
  95. {// The client suspends the connection.
  96. HttpContext. Response. BinaryWrite (br. ReadBytes (packSize ));
  97. HttpContext. Response. Flush ();
  98. If (sleep> 1) Thread. Sleep (sleep );
  99. }
  100. # Endregion
  101. }
  102. Catch
  103. {
  104. Ret = false;
  105. }
  106. Finally
  107. {
  108. Br. Close ();
  109. MyFile. Close ();
  110. }
  111. }
  112. Catch
  113. {
  114. Ret = false;
  115. }
  116. Return ret;
  117. }



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.