Maison > interface Web > js tutoriel > le corps du texte

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

青灯夜游
Libérer: 2023-03-09 19:37:01
avant
1670 Les gens l'ont consulté

Comment utiliser le module http de Node.js pour traiter les téléchargements de fichiers ? L'article suivant explique comment traiter les fichiers téléchargés par le front-end côté serveur. J'espère qu'il sera utile à tout le monde !

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

Afficher les données de la demande

Si les données que nous envoyons maintenant au serveur sont telles qu'indiquées dans la figure ci-dessous, elles contiennent des informations de champ ordinaires nom et un fichier image fichier code>:<code>name 以及一个图片文件 file

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

我们先来看看如何在服务器接收到文件上传的数据,并在调试控制台打印查看:

const http = require(&#39;http&#39;)
const server = http.createServer((req, res) => {
  req.setEncoding(&#39;binary&#39;)
  req.on(&#39;data&#39;, data => {
    console.log(data)
  })
  req.on(&#39;end&#39;, () => {
    console.log(&#39;上传结束&#39;)
    res.end(&#39;上传成功&#39;)
  })
})
server.listen(3010, () => console.log(&#39;服务器开启&#39;))
Copier après la connexion

想要能看懂打印的结果,我们通过 req.setEncoding(&#39;binary&#39;) 设置了字符编码为 &#39;binary&#39;,这样得到的数据就不是 buffer 对象而是 ASCII 编码后的字符串,我们就可以使用一些字符串的方法来处理数据了。

但是当文件大小比较大时,直接通过在命令行输入 node 或 nodemon 来运行代码,得到的数据无法完全在控制台展示。所以我们可以在要打印请求数据的地方打上断点,通过 debugger 的模式来运行代码:

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

点击 "运行和调试" 后,vs code 就会帮我们把服务器运行起来了:

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

之后当我们发送了上传的请求,再点击下图右上角的 "单步跳过",就可以看到请求的数据了 —— 那些可以被 ASCII 编译的信息,比如英文字母,可以直接看到了,而图片的数据则是一堆乱码:

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

接下来就是处理获取的请求数据,将里面的图片数据截取出来然后通过写入流生成图片。

处理文件(图片)数据

获取图片数据

因为可读流&#39;data&#39; 事件一次最多读取 64kb 的数据,当图片比较大时,可能会触发多次,所以我们定义变量 reqData 来存储请求发来的数据:

let reqData = &#39;&#39;
req.on(&#39;data&#39;, data => {
  reqData += data
})
req.on(&#39;end&#39;, () => {
  console.log(reqData) // 在这行打断点
  res.end(&#39;上传成功&#39;)
})
Copier après la connexion

req 触发了 &#39;end&#39; 事件说明请求数据读取完毕,如果在上列代码的第 6 行 console.log(reqData) 处打个断点,然后查看 reqData,得到的数据如下:

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

图片的数据应该是 image/pngrnrnrn----------------------------158329774739626517859573--rn 中间这段。我们可以去获取图片数据的起(imgDataStartIndex)止(imgDataEndIndex)位置的 index,然后使用 substring() 做个截取,最后再使用 trim() 方法去除首位的空格 rn

const imgType = &#39;image/png&#39;
const imgDataStartIndex = reqData.indexOf(imgType) + imgType.length
const imgDataEndIndex = reqData.indexOf(`--${boundary}--`)
const imgData = reqData.substring(imgDataStartIndex, imgDataEndIndex).trim()
Copier après la connexion

获取分隔符 boundary

--------------------------158329774739626517859573是客户端随机生成的,用于分割表单里的每段数据的分隔符(boundary),在每个表单项的开头和结尾都有,并且在开头处的前面都会加上两个减号 --,在整个表单数据结束处的末尾也会加上两个减号。查看请求头:

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

可以发现在 content-type 里定义了boundary,于是我们可以使用如下方法获取分隔符:

const boundary = req.headers[&#39;content-type&#39;].split(&#39;boundary=&#39;)[1]
Copier après la connexion

生成图片

获取到了图片数据 imgData 后,就可以通过 fswriteFile() 写入文件生成图片了:

fs.writeFile(&#39;./img.png&#39;, imgData, &#39;binary&#39;, err => {
  if (!err) console.log(&#39;图片写入成功&#39;)
})
Copier après la connexion

注意需要在第三个参数传入&#39;binary&#39; 来设定 encoding

Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers

Voyons d'abord comment recevoir les données du fichier téléchargé sur le serveur et les imprimer sur la console de débogage :
const http = require('http')
const fs = require('fs')

const server = http.createServer((req, res) => {
  req.setEncoding(&#39;binary&#39;)
  const boundary = req.headers[&#39;content-type&#39;].split(&#39;boundary=&#39;)[1]
  let reqData = ''
  req.on(&#39;data&#39;, data => {
    reqData += data
  })
  req.on(&#39;end&#39;, () => {
    const imgType = 'image/png'
    const imgDataStartIndex = reqData.indexOf(imgType) + imgType.length
    const imgDataEndIndex = reqData.indexOf(`--${boundary}--`)
    const imgData = reqData.substring(imgDataStartIndex, imgDataEndIndex).trim()
    fs.writeFile('./img.png', imgData, &#39;binary&#39;, err => {
      if (!err) console.log('图片写入成功')
    })
    res.end('上传成功')
  })
})

server.listen(3010, () => console.log('服务器开启'))
Copier après la connexion
Copier après la connexion

Pour comprendre les résultats imprimés, nous passons req.setEncoding('binary') Définissez le codage des caractères sur 'binary', afin que les données obtenues ne soient pas un objet tampon mais une chaîne codée en ASCII. Nous pouvons utiliser certaines méthodes de chaîne pour traiter les données.

Mais lorsque la taille du fichier est relativement importante, les données obtenues ne peuvent pas être entièrement affichées sur la console en tapant directement node ou nodemon sur la ligne de commande pour exécuter le code. Nous pouvons donc mettre un point d'arrêt à l'endroit où nous voulons imprimer les données de la requête et exécuter le code via le mode débogueur : 🎜🎜Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers🎜🎜Après avoir cliqué sur "Exécuter et déboguer", vs code nous aidera à exécuter le serveur : 🎜🎜Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers🎜🎜Après cela, lorsque nous envoyons la demande de téléchargement, cliquez sur " Single Step Skip" dans le coin supérieur droit de l'image ci-dessous pour voir les données demandées - les informations qui peuvent être compilées par ASCII, telles que les lettres anglaises, peuvent être vues directement, tandis que les données dans l'image sont un tas de caractères tronqués : 🎜🎜Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers🎜🎜Connectez-vous L'étape suivante consiste à traiter les données de requête obtenues, à intercepter les données d'image à l'intérieur, puis à générer l'image en écrivant dans le flux. 🎜🎜🎜Traitement des données de fichier (image)🎜🎜🎜🎜Obtenir des données d'image🎜🎜🎜Parce que 'data' du flux lisible peut lire jusqu'à 64 Ko à une donnée temporelle, lorsque l'image est relativement volumineuse, peut être déclenchée plusieurs fois, nous définissons donc la variable reqData pour stocker les données envoyées par la requête : 🎜rrreee🎜Quand req</code > déclenche <code >'end' La description de l'événement est que les données demandées ont été lues. Si vous définissez un point d'arrêt à la ligne 6 du code ci-dessus console.log(reqData), puis visualisez reqData , les données obtenues sont les suivantes : 🎜🎜Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers🎜🎜Les données de l'image doivent être image/pngrnrn et rn---------- ----------- -------158329774739626517859573--rn Le paragraphe du milieu. Nous pouvons obtenir l'index des positions de début (imgDataStartIndex) et de fin (imgDataEndIndex) des données d'image, puis utiliser substring() pour interceptez-le, et enfin utilisez ensuite la méthode trim() pour supprimer l'espace de début rn : 🎜rrreee

🎜Obtenez le la limite du séparateur🎜

🎜----------------------------------------158329774739626517859573 est générée aléatoirement par le client et utilisée pour diviser chaque paragraphe du formulaire Le délimiteur de données (limite) se trouve au début et à la fin de chaque élément du formulaire, et deux signes moins -- sont ajoutés devant le début et à la fin de l'intégralité des données du formulaire Il y aura également deux signes moins à la fin. Consultez l'en-tête de la demande : 🎜🎜Une brève analyse de la façon dont le module http de Node gère les téléchargements de fichiers🎜🎜Vous pouvez constater que boundary est défini dans content-type, nous pouvons donc utiliser la méthode suivante pour obtenir le séparateur : 🎜rrreee🎜🎜Générer une image🎜🎜🎜Après avoir obtenu les données d'image imgData, vous pouvez transmettre le writeFile() de fs écrit le fichier pour générer l'image : 🎜rrreee 🎜Notez qu'il doit être dans la troisième étape. Passer les paramètres dans 'binary' pour définir le encodage. 🎜🎜🎜Résumé🎜🎜🎜Maintenant, le code est résumé comme suit :🎜
const http = require('http')
const fs = require('fs')

const server = http.createServer((req, res) => {
  req.setEncoding(&#39;binary&#39;)
  const boundary = req.headers[&#39;content-type&#39;].split(&#39;boundary=&#39;)[1]
  let reqData = ''
  req.on(&#39;data&#39;, data => {
    reqData += data
  })
  req.on(&#39;end&#39;, () => {
    const imgType = 'image/png'
    const imgDataStartIndex = reqData.indexOf(imgType) + imgType.length
    const imgDataEndIndex = reqData.indexOf(`--${boundary}--`)
    const imgData = reqData.substring(imgDataStartIndex, imgDataEndIndex).trim()
    fs.writeFile('./img.png', imgData, &#39;binary&#39;, err => {
      if (!err) console.log('图片写入成功')
    })
    res.end('上传成功')
  })
})

server.listen(3010, () => console.log('服务器开启'))
Copier après la connexion
Copier après la connexion

上述代码能够成功运行还有一些限制,比如只能处理单文件上传,且文件需要是 png 格式的图片,并且放在表单最后一项。文章的目的在于简单了解使用 node 的 http 模块搭建的服务器大体上是如何处理上传文件的请求的,为将来深入学习其它基于 http 模块的框架(express.js、koa.js 等)打好基础。

更多node相关知识,请访问: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!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!