Home > Web Front-end > JS Tutorial > Implement segmented download function based on http Range Requests protocol

Implement segmented download function based on http Range Requests protocol

不言
Release: 2018-10-17 14:40:54
forward
6126 people have browsed it

The content this article brings to you is about the function of implementing segmented downloads based on the http Range Requests protocol. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

This article is based on the http Range Requests protocol and implements the function of segmented download.

Usage scenarios include browser-based streaming file segment transmission, client-based segmented downloading, etc.

Principle

http uses the headers related to Range Requests to negotiate with the server to implement partial requests.

The implementation process is posted below. The code can be viewed in git: https://github.com/keller35/partial.

Server code

The server is implemented using node:

const fs = require('fs');
const path = require('path');
const Koa = require('koa');

const app = new Koa();
const PATH = './resource';

app.use(async ctx => {
    const file = path.join(__dirname, `${PATH}${ctx.path}`);
    // 1、404检查
    try {
        fs.accessSync(file);
    } catch (e) {
        return ctx.response.status = 404;
    }
    const method = ctx.request.method;
    const { size } = fs.statSync(file);
    // 2、响应head请求,返回文件大小
    if ('HEAD' == method) {
        return ctx.set('Content-Length', size);
    }
    const range = ctx.headers['range'];
    // 3、通知浏览器可以进行分部分请求
    if (!range) {
        return ctx.set('Accept-Ranges', 'bytes');
    }
    const { start, end } = getRange(range);
    // 4、检查请求范围
    if (start >= size || end >= size) {
        ctx.response.status = 416;
        return ctx.set('Content-Range', `bytes */${size}`);
    }
    // 5、206分部分响应
    ctx.response.status = 206;
    ctx.set('Accept-Ranges', 'bytes');
    ctx.set('Content-Range', `bytes ${start}-${end ? end : size - 1}/${size}`);
    ctx.body = fs.createReadStream(file, { start, end });
});

app.listen(3000, () => console.log('partial content server start'));

function getRange(range) {
    var match = /bytes=([0-9]*)-([0-9]*)/.exec(range);
    const requestRange = {};
    if (match) {
        if (match[1]) requestRange.start = Number(match[1]);
        if (match[2]) requestRange.end = Number(match[2]);
    }
    return requestRange;
}
Copy after login

The functional logic implemented by the code is roughly:

  1. For requests Check the resource. If it does not exist, respond with 404

  2. For HEAD request, return the resource size

  3. If the GET request does not inform the range, return Content -Length, informs the browser that it can perform fragmented requests

  4. If the request sets a range, check whether the range is legal, and if it is not legal, return a legal range

  5. Everything is normal, get the range part of the file, and make a stream response

The code is very simple, just implement the Range Requests protocol once and it will be ok. Of course, the content of the protocol is not fully implemented here. , but that suffices for the demonstration here.

The server code is ok, use a browser demo to check it out.

Browser example

Modern browsers basically implement Range Requests. The audio tag is used as an example here.

    
        <title>分片流传输</title>
        <script>
            function jump() {
                const player = document.getElementById(&#39;musicPlayer&#39;);
                // 从30s开始播放
                player.currentTime = 30;
            }
        </script>
    
    
        <audio></audio>
        <button>切到30s</button>
    
Copy after login

The final effect is like this:

Implement segmented download function based on http Range Requests protocol

Implement segmented download function based on http Range Requests protocol

Compare the two pictures. When the html is loaded, the browser Automatically request resources. At this time, the header has Range: bytes=0-, which means that the resource is loaded from the 0th byte; when the click jumps to 30s to play, the header becomes Range: bytes=3145728-.

Similarly using this server code, you can also implement a client to simulate subcontracted downloads.

node sub-package download

This example demonstrates how to concurrently download parts of a resource and then merge it into one file.

This is also implemented using node:

import request from 'request';
import path from 'path';
import fs from 'fs';

const SINGLE = 1024 * 1000;
const SOURCE = 'http://127.0.0.1:3000/source.mp3';

request({
    method: 'HEAD',
    uri: SOURCE,
}, (err, res) => {
    if (err) return console.error(err);
    const file = path.join(__dirname, './download/source.mp3');
    try {
        fs.closeSync(fs.openSync(file, 'w'));
    } catch (err) {
        return console.error(err);
    }
    const size = Number(res.headers['content-length']);
    const length = parseInt(size / SINGLE);
    for (let i=0; i<length> {
            const range = resp.headers['content-range'];
            const match = /bytes ([0-9]*)-([0-9]*)/.exec(range);
            start = match[1];
            end = match[2];
        }).pipe(fs.createWriteStream(file, {start, end}));
    }
});</length>
Copy after login

The code is relatively simple, which is to open multiple http requests, download resources concurrently, and then write to the corresponding location of the file according to the content-range of the response.

The above is the detailed content of Implement segmented download function based on http Range Requests protocol. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template