>  기사  >  웹 프론트엔드  >  http Range Requests 프로토콜을 기반으로 분할된 다운로드 기능 구현

http Range Requests 프로토콜을 기반으로 분할된 다운로드 기능 구현

不言
不言앞으로
2018-10-17 14:40:546081검색

이 기사의 내용은 http Range Requests 프로토콜을 기반으로 분할 다운로드를 구현하는 기능에 대한 내용입니다. 필요한 친구들이 참고할 수 있기를 바랍니다.

이 글은 http Range Requests 프로토콜을 기반으로 하며 분할된 다운로드 기능을 구현합니다.

사용 시나리오에는 브라우저 기반 스트리밍 파일 조각 전송, 클라이언트 기반 분할 다운로드 등이 포함됩니다.

Principle

http는 Range Requests 관련 헤더를 통해 서버와 협상하여 부분 요청을 구현할 수 있습니다.

구현 과정은 아래에 게시되어 있습니다: https://github.com/keller35/partial.

서버 코드

서버는 노드를 사용하여 구현됩니다.

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;
}

코드로 구현된 기능적 논리는 대략 다음과 같습니다.

#🎜 🎜#
  1. 요청한 리소스를 확인하고, 존재하지 않으면 404로 응답하세요

  2. HEAD 요청의 경우 리소스 크기를 반환합니다#🎜 🎜##🎜🎜 #

    GET 요청이 범위를 알려주지 않으면 Content-Length가 반환되어 브라우저에 조각 요청이 가능함을 알립니다.
  3. # 🎜🎜#

    요청에서 범위를 설정한 경우 해당 범위가 적합한지 확인하고, 적합하지 않은 경우 적합한 범위를 반환합니다.

  4. Everything 정상입니다. 파일의 범위 부분을 가져와 스트림 응답을 만듭니다

  5. # 🎜🎜#
  6. 코드는 매우 간단합니다. 범위 요청 프로토콜을 구현하면 괜찮습니다. 물론 프로토콜의 내용이 여기에서 완전히 구현되지는 않았지만 여기에서 시연의 요구 사항을 충족했습니다.

    서버 코드는 정상입니다. 브라우저 데모를 사용하여 확인해 보세요.
Browser example

최신 브라우저는 기본적으로 범위 요청을 구현합니다. 여기서는 오디오 태그가 예로 사용됩니다.

    
        <title>分片流传输</title>
        <script>
            function jump() {
                const player = document.getElementById(&#39;musicPlayer&#39;);
                // 从30s开始播放
                player.currentTime = 30;
            }
        </script>
    
    
        <audio></audio>
        <button>切到30s</button>
    
최종 효과는 다음과 같습니다.

http Range Requests 프로토콜을 기반으로 분할된 다운로드 기능 구현비교 두 그림, HTML이 로드되면 브라우저가 자동으로 리소스를 요청하고 헤더에

이 있습니다.

http Range Requests 프로토콜을 기반으로 분할된 다운로드 기능 구현이 서버 코드를 사용하여 유사하게 클라이언트를 구현하여 하도급 다운로드를 시뮬레이션할 수도 있습니다.

노드 하위 패키지 다운로드Range: bytes=0-,表示从第0 byte开始加载资源;当点击跳到30s处播放时,此时header变成了Range: bytes=3145728-

이 예에서는 리소스의 일부를 동시에 다운로드한 다음 이를 하나의 파일로 병합하는 방법을 보여줍니다.

이것은 또한 노드를 사용하여 구현됩니다:

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>

코드는 비교적 간단합니다. 여러 http 요청을 열고 리소스를 동시에 다운로드한 다음 다음에 따라 파일에 쓰는 것입니다. 해당 위치의 내용 범위.

위 내용은 http Range Requests 프로토콜을 기반으로 분할된 다운로드 기능 구현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제