In diesem Artikel geht es um die Implementierung segmentierter Downloads basierend auf dem HTTP Range Requests-Protokoll. Ich hoffe, dass er für Sie hilfreich ist.
Dieser Artikel implementiert die segmentierte Download-Funktion basierend auf dem http Range Requests-Protokoll.
Nutzungsszenarien umfassen browserbasierte Streaming-Dateisegmentübertragung, clientbasiertes segmentiertes Herunterladen usw.
http kann über den Header im Zusammenhang mit Bereichsanforderungen mit dem Server verhandeln, um Teilanforderungen zu implementieren.
Der Implementierungsprozess ist unten aufgeführt. Der Code kann in Git eingesehen werden: https://github.com/keller35/partial.
Der Server wird mithilfe des Knotens implementiert:
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; }
Die durch den Code implementierte Funktionslogik ist ungefähr:
Anfrage Überprüfen Sie die Ressource. Wenn sie nicht vorhanden ist, antworten Sie mit 404
Bei HEAD-Anfrage die Ressourcengröße zurückgeben
Bei GET-Anfrage informiert den Bereich nicht, gibt Content -Length zurück, informiert den Browser darüber, dass er fragmentierte Anfragen ausführen kann
Wenn die Anfrage einen Bereich festlegt, prüfen Sie, ob der Bereich zulässig ist und ob dies der Fall ist nicht zulässig, geben Sie einen zulässigen Bereich zurück
Alles ist normal, holen Sie sich den Bereichsteil der Datei und erstellen Sie eine Stream-Antwort
Der Code ist Sehr einfach. Implementieren Sie das Range Requests-Protokoll einfach einmal und es ist in Ordnung. Natürlich gibt es keine vollständige Implementierung des Protokolls, aber das reicht für die Demonstration.
Der Servercode ist in Ordnung. Verwenden Sie eine Browser-Demo, um ihn zu überprüfen.
Moderne Browser implementieren grundsätzlich Range Requests, hier wird der Audio-Tag als Beispiel verwendet.
<title>分片流传输</title> <script> function jump() { const player = document.getElementById('musicPlayer'); // 从30s开始播放 player.currentTime = 30; } </script> <audio></audio> <button>切到30s</button>
Der Endeffekt sieht so aus:
Vergleichen Sie die beiden Bilder Browser Fordern Sie zu diesem Zeitpunkt automatisch Ressourcen an. Dies bedeutet, dass die Ressourcen ab dem 0. Byte geladen werden. Wenn Sie zum Abspielen auf 30 Sekunden klicken, wird der Header zu Range: bytes=0-
. 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>
Das obige ist der detaillierte Inhalt vonImplementieren Sie eine segmentierte Download-Funktion basierend auf dem HTTP Range Requests-Protokoll. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!