Detailed Explanation of PHP Implementation of File Download Breakpoint Continued Transfer

  • 2021-07-22 09:11:48
  • OfStack

If our website provides file download service, we usually want the download to resume at Breakpoint (Resumable Download), which means that users can pause the download and continue downloading from the pause at some time in the future without having to download the whole file again.

Typically, an Web server, such as Apache, has support for breakpoint continued transmission turned on by default. Therefore, if you download files directly through the Web server, you can enjoy the benefits of breakpoint continuous transmission without special configuration. Because these files are downloaded directly through the Web server, the back-end scripts cannot control the download process. This is not a problem for websites that only provide public and static files, but for websites that need to provide private and dynamic files, downloading directly through Web server cannot meet the demand. At this time, it is necessary to add support for breakpoint continuous transmission when writing background scripts.

Taking PHP as an example, this paper briefly introduces the method of realizing breakpoint continuous transfer of file download.

Principle

The principle of breakpoint continuous transmission is quite intuitive.

The HTTP protocol specifies how to transmit part of a resource, not all of it. For example, if a file is 1000 bytes in size, the browser can request only the first 300 bytes of the file, or only the 500th to 1000th bytes. In this way, instead of transmitting the entire content of a resource in one request, you can initiate multiple requests, requesting only one part of the content at a time. After all these requests are returned, splice the obtained contents one by one to get the complete resources.

To realize breakpoint continuous transmission, we should make use of the above characteristics of HTTP protocol. When the user pauses the download, the browser will record where the download has been downloaded. When the user resumes downloading at a certain time in the future, he can continue downloading from the last paused location without starting from scratch.

Realization

Since partial transfer is not mandatory, and the server may or may not support it, we need to tell the browser in the program whether the resource it requests supports partial transfer. This can be done by setting the Accept-Ranges response header information for HTTP. The PHP code is as follows:


header('Accept-Ranges: bytes');

Accept-Ranges: bytes tells the browser that the resource supports partial transfers in bytes. This response header needs to be attached to all resources that support partial transmission.

When one request is received, we need to extract which part of the resource the browser is requesting from the browser's request. This information is passed through the Range request header. In PHP, it is stored in $_SERVER ['HTTP_RANGE']. We need to check if the variable is defined, and if so, use the value, otherwise, set range to the entire resource.


$range = "0-". ($content_length-1);
if(isset($_SERVER['HTTP_RANGE'])){
    $range = $_SERVER['HTTP_RANGE'];
}

Next, you need to analyze the value of $range to decide which part of the resource to return. Examples of possible values:

100-200 // No. 1 100 To the first 200 Byte
500-    // No. 1 500 Byte to end of file
-1000   // Last 1000 Bytes

It should be noted here that after getting an Range, you need to check its value, including:

1. The starting position is non-negative
2. End position needs to be greater than start position
3. The starting position needs to be less than the file length minus 1 (because the position index here starts from 0)
4. If the end position is greater than file length minus 1, you need to set its value to file length minus 1

If the value of Range is illegal, you need to terminate the program and inform the browser:


header('HTTP/1.1 416 Requested Range Not Satisfiable');

In order to keep the article concise, the specific verification code is not provided here. Let's assume that you have checked the value of Range and got two variables, $start and $end, which represent the start position and the end position respectively.

The next thing to do is to send the contents of the corresponding part of the file to the browser. However, it should be noted that this involves sending multiple HTTP response header information, as follows:


header('HTTP/1.1 206 Partial Content');
header('Accept-Ranges: bytes');
header("Content-Range: bytes $start-$end/$filesize");
$length = $end - $start + 1;
header("Content-Length: $length"); /* The specified part of the output file */

Here, $length needs to be noted under 1, and its value is the length of the content transferred this time, not the length of the whole file. Another point to note is that the HTTP status code here is 206, not 200.

Summarize

In fact, the breakpoint transmission of file download makes use of the support of transferring some files in HTTP protocol. This 1 feature of HTTP protocol can not only be used to realize breakpoint continuous transmission, but also can be used by client programs to realize multi-thread download.

In the process of realizing breakpoint continuous transmission, attention should be paid to correctly setting various HTTP header information. Incorrect header information will cause the file downloaded by the user to be damaged and unusable.


Related articles: