0

0

浅析Node中http模块怎么处理文件上传

青灯夜游

青灯夜游

发布时间:2023-03-09 19:37:01

|

2014人浏览过

|

来源于掘金社区

转载

怎么使用node.js的http模块处理文件上传?下面本篇文章就来看看在服务器端要如何处理前端上传的文件,希望对大家有所帮助!

浅析Node中http模块怎么处理文件上传

查看请求数据

如果我们现在向服务器发送的数据如下图所示,里面包含了普通的字段信息 name 以及一个图片文件 file

1.png

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

const http = require('http')
const server = http.createServer((req, res) => {
  req.setEncoding('binary')
  req.on('data', data => {
    console.log(data)
  })
  req.on('end', () => {
    console.log('上传结束')
    res.end('上传成功')
  })
})
server.listen(3010, () => console.log('服务器开启'))

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

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

2.png

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

3.png

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

4.png

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

处理文件(图片)数据

获取图片数据

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

Prisma
Prisma

Prisma是一款照片编辑工具,用户可以轻松地将照片转换成数字艺术。

下载
let reqData = ''
req.on('data', data => {
  reqData += data
})
req.on('end', () => {
  console.log(reqData) // 在这行打断点
  res.end('上传成功')
})

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

5.png

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

const imgType = 'image/png'
const imgDataStartIndex = reqData.indexOf(imgType) + imgType.length
const imgDataEndIndex = reqData.indexOf(`--${boundary}--`)
const imgData = reqData.substring(imgDataStartIndex, imgDataEndIndex).trim()

获取分隔符 boundary

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

6.png

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

const boundary = req.headers['content-type'].split('boundary=')[1]

生成图片

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

fs.writeFile('./img.png', imgData, 'binary', err => {
  if (!err) console.log('图片写入成功')
})

注意需要在第三个参数传入'binary' 来设定 encoding

总结

现将代码汇总如下:

const http = require('http')
const fs = require('fs')

const server = http.createServer((req, res) => {
  req.setEncoding('binary')
  const boundary = req.headers['content-type'].split('boundary=')[1]
  let reqData = ''
  req.on('data', data => {
    reqData += data
  })
  req.on('end', () => {
    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, 'binary', err => {
      if (!err) console.log('图片写入成功')
    })
    res.end('上传成功')
  })
})

server.listen(3010, () => console.log('服务器开启'))

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

更多node相关知识,请访问:nodejs 教程

相关专题

更多
node.js调试
node.js调试

node.js调试可以使用console.log()输出调试信息、断点调试和第三方调试工具。详细介绍:1、console.log()输出调试信息,通过在代码中插入console.log()语句,开发人员可以在控制台输出变量的值、函数的执行结果等信息,以便观察代码的执行流程和状态;2、断点调试,可以在代码中设置断点,以便在特定位置暂停代码的执行,观察变量的值和执行流程等。

347

2023.09.19

JavaScript 全栈开发基础(Node.js + 前端)
JavaScript 全栈开发基础(Node.js + 前端)

本专题系统介绍 JavaScript 在全栈开发中的核心知识结构,涵盖 Node.js 基础、Express/Koa 接口构建、前端交互设计、模块化与包管理、数据库连接、前后端数据通信与部署流程。通过完整项目示例,帮助学习者掌握从浏览器到服务器的一体化开发能力,实现真正意义上的全栈入门。

93

2025.11.26

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

258

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1468

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

621

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

551

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

566

2024.04.29

html编辑相关教程合集
html编辑相关教程合集

本专题整合了html编辑相关教程合集,阅读专题下面的文章了解更多详细内容。

16

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 6.8万人学习

前端基础到实战(HTML5+CSS3+ES6+NPM)
前端基础到实战(HTML5+CSS3+ES6+NPM)

共162课时 | 19万人学习

第二十二期_前端开发
第二十二期_前端开发

共119课时 | 12.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号