Maison  >  Article  >  interface Web  >  Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)

Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)

青灯夜游
青灯夜游avant
2022-01-17 19:16:383163parcourir

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 !

Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)

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();

Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)

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(&#39;文件读取错误&#39;);
      } else {
        resolve(data);
      }
    })
  })
}

// 封装文件压缩方法
const gzip = async (paramsData) => {
  return new Promise((resolve, reject) => {
    zlib.gzip(paramsData, (err, result) => {
      if(err) {
        reject(&#39;文件压缩错误&#39;);
      } 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 + &#39;/file.txt&#39;);
  res.write(buffer);
  res.end();
})
server.listen(3000, () => {
  console.log(`server启动成功`)
})

Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)

// 实现一个简单的文件读取服务器(开启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 + &#39;/file.txt&#39;);
  const gzipData = await gzip(buffer);
  res.write(gzipData);
  res.end();
})
server.listen(3000, () => {
  console.log(`server启动成功`)
})

Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)

2. 通过数据分块传输

有场景需要用从数据库中查询获得的数据生成一个大的 HTML 表格的时候,或者需要传输大量的图片的时候,可以通过分块传输实现。

Transfer-Encoding: chunked
Transfer-Encoding: gzip, chunked

响应头 Transfer-Encoding 字段的值为 chunked,表示数据以一系列分块的形式进行发送。需要注意的是 Transfer-Encoding 和 Content-Length 这两个字段是互斥的,也就是说响应报文中这两个字段不能同时出现。

// 数据分块传输
const spilitChunks = async () =>{
  const buffer = await readFile(__dirname + &#39;/file.txt&#39;);
  const lines = buffer.toString(&#39;utf-8&#39;).split(&#39;\n&#39;);
  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 transmettra accepter 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 gzipn'est pas activé > et l'effet de l'activation de gzip. 🎜rrreee🎜Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)🎜rrreee 🎜Comment implémenter le transfert HTTP de gros fichiers basé sur nodejs ? (Partage de méthodes pratiques)🎜🎜🎜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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer