Maison > Article > interface Web > Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)
Basé sur nodeComment implémenter http pour transférer des fichiers volumineux ? L'article suivant vous présentera plusieurs solutions pratiques de transfert de fichiers http basées sur nodejs. J'espère qu'il vous sera utile !
La solution de transfert de fichiers http basée sur nodejs joue un rôle très important dans le développement full-stack front-end et back-end actuel. Dans cet article, j'utiliserai plusieurs solutions pour implémenter le transfert http de grande taille. fichiers. Avant d'implémenter la fonction, nous écrivons d'abord un gros fichier via le module fs de nodejs et générons un fichier local dans le projet :
const fs = require('fs'); const writeStream = fs.createWriteStream(__dirname + "/file.txt"); for(let i = 0;i <= 100000; i++) { writeStream.write(`${i} —— 我是${i}号文件\n`, "utf-8"); } writeStream.end();
Une fois le code ci-dessus exécuté avec succès, une taille sera générée dans le répertoire d'exécution actuel. Il s'agit d'un fichier texte de taille 3,2 Mo, qui sera utilisé comme "matériel de gros fichier" pour les solutions suivantes. Avant d'énumérer le schéma de transfert de fichiers volumineux, nous encapsulons d'abord les deux méthodes publiques qui seront utilisées plus tard : Méthode de lecture de fichiers
et Méthode de compression de fichiers
: 文件读取方法
和 文件压缩方法
:
// 封装读取文件的方法 const readFile = async (paramsData) => { return new Promise((resolve, reject) => { fs.readFile(paramsData, (err, data) => { if(err) { reject('文件读取错误'); } else { resolve(data); } }) }) } // 封装文件压缩方法 const gzip = async (paramsData) => { return new Promise((resolve, reject) => { zlib.gzip(paramsData, (err, result) => { if(err) { reject('文件压缩错误'); } else { resolve(result); } }) }) }
1. 通过大文件在数据压缩后传输
浏览器在发送请求时,都会携带 accept
和 accept-*
请求头信息,用于告诉服务器当前浏览器所支持的文件类型、支持的压缩格式列表和支持的语言。请求头中的 Accept-Encoding
字段,用于将客户端能够理解的内容编码方式(通常是某种压缩算法)告诉给服务端。服务端会选择一个客户端所支持的方式,并通过响应头 Content-Encoding
来通知客户端该选择,响应头告诉浏览器返回的 JS 脚本,是经过 gzip
压缩算法处理过的
// 请求头 accept-encoding: gzip, deflate, br
// 响应头 cache-control: max-age=2592000 content-encoding: gzip content-type: application/x-javascript
基于 Accept-Encoding
和 Content-Encoding
字段的了解,我们来验证一下未开启 gzip
和开启 gzip
的效果。
// 实现一个简单的文件读取服务器(没有开启gzip) const server = http.createServer(async (req, res) => { res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8", }); const buffer = await readFile(__dirname + '/file.txt'); res.write(buffer); res.end(); }) server.listen(3000, () => { console.log(`server启动成功`) })
// 实现一个简单的文件读取服务器(开启gzip) const server = http.createServer(async(req, res) => { res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8", "Content-Encoding": "gzip" }); const buffer = await readFile(__dirname + '/file.txt'); const gzipData = await gzip(buffer); res.write(gzipData); res.end(); }) server.listen(3000, () => { console.log(`server启动成功`) })
2. 通过数据分块传输
有场景需要用从数据库中查询获得的数据生成一个大的 HTML 表格的时候,或者需要传输大量的图片的时候,可以通过分块传输实现。
Transfer-Encoding: chunked Transfer-Encoding: gzip, chunked
响应头 Transfer-Encoding
字段的值为 chunked
,表示数据以一系列分块的形式进行发送。需要注意的是 Transfer-Encoding
和 Content-Length
这两个字段是互斥的,也就是说响应报文中这两个字段不能同时出现。
// 数据分块传输 const spilitChunks = async () =>{ const buffer = await readFile(__dirname + '/file.txt'); const lines = buffer.toString('utf-8').split('\n'); let [chunks, i, n] = [[], 0, lines.length]; while(i < n) { chunks.push(lines.slice(i, i+= 10)); }; return chunks; } const server = http.createServer(async(req, res) => { res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8", "Transfer-Encoding": "chunked", "Access-Control-Allow-Origin": "*", }); const chunks = await spilitChunks(); for(let i =0; i< chunks.length; i++) { setTimeout(() => { let content = chunks[i].join("&"); res.write(`${content.length.toString(16)}\r\n${content}\r\n`); }, i * 1000); } setTimeout(() => { res.end(); }, chunks.length * 1000); }) server.listen(3000, () => { console.log(`server启动成功`) })
3. 通过数据流的形式传输
当使用 Node.js
向客户端返回大文件时,使用流的形式来返回文件流能避免处理大文件时,占用过多的内存。具体实现方式如下所示。当使用流的形式来返回文件数据时,HTTP 响应头 Transfer-Encoding
字段的值为 chunked
const server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/plain;charset=utf-8", "Content-Encoding": "gzip", "Transfer-Encoding": "chunked" }); fs.createReadStream(__dirname + "/file.txt") .setEncoding("utf-8") .pipe(zlib.createGzip()) .pipe(res); }) server.listen(3000, () => { console.log(`server启动成功`) })
1. Transmettre via des fichiers volumineux après compression des données
Lorsque le navigateur envoie une requête, il transmettraaccepter
et accepter- *
les informations d'en-tête de requête sont utilisées pour indiquer au serveur les types de fichiers pris en charge par le navigateur actuel, la liste des formats de compression pris en charge et les langues prises en charge. Le champ Accept-Encoding
dans l'en-tête de la requête est utilisé pour indiquer au serveur la méthode de codage du contenu (généralement un certain algorithme de compression) que le client peut comprendre. Le serveur choisira une méthode prise en charge par le client et informera le client du choix via l'en-tête de réponse Content-Encoding
. L'en-tête de réponse indique au navigateur que le script JS renvoyé est transmis via gzip.
Algorithme de compression traité 🎜rrreeerrreee🎜Sur la base de la compréhension des champs Accept-Encoding
et Content-Encoding
, vérifions que gzip
n'est pas activé > et l'effet de l'activation de gzip
. 🎜rrreee🎜🎜rrreee 🎜🎜🎜🎜2. Transmission via des blocs de données🎜🎜🎜Il existe des scénarios dans lesquels il est nécessaire de générer un grand tableau HTML à l'aide des données obtenues à partir de la requête de base de données, ou lorsqu'un grand tableau HTML est généré. quantité de données doit être transférée. Les images peuvent être transmises en morceaux. 🎜rrreee🎜La valeur du champ Transfer-Encoding
dans l'en-tête de réponse est chunked
, ce qui signifie que les données sont envoyées dans une série de morceaux. Il est à noter que les deux champs Transfer-Encoding
et Content-Length
s'excluent mutuellement, ce qui signifie que ces deux champs ne peuvent pas apparaître en même temps dans le message de réponse. 🎜rrreee🎜🎜3. Transmission via un flux de données🎜🎜🎜Lors de l'utilisation de Node.js
pour renvoyer des fichiers volumineux au client Quand en utilisant un flux pour renvoyer un flux de fichiers, vous pouvez éviter de prendre trop de mémoire lors du traitement de fichiers volumineux. La mise en œuvre spécifique est la suivante. Lorsque vous utilisez le formulaire de flux pour renvoyer des données de fichier, la valeur du champ Transfer-Encoding
de l'en-tête de réponse HTTP est chunked
, indiquant que les données sont envoyées dans une série de morceaux. 🎜rrreee🎜Pour plus de connaissances sur les nœuds, veuillez visiter : 🎜tutoriel Nodejs🎜 ! ! 🎜Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!