用Node处理文件上传
前言
在Web开发中,文件上传是一个非常常见、非常重要的功能。本文将介绍如何用Node处理上传的文件。
需求分析
由于现在前后端分离很流行,那么本文也直接采用前后端分离
的做法。前端界面如下:
用户从浏览器中选择文件,点击上传,将发起http请求到服务器,服务器将接受到的文件存储在服务器硬盘中。
前端部分
ajax请求库采用axios,为了简化说明,前端限制上传的文件类型只能为图片,且一次只能上传一张,有兴趣的朋友可以自行补充,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<input type="file" name="file" accept="image/*" onchange="changeImg(event)"/>
<button onclick="submit()">上传</button>
<script>
let file = ''
let fileName = ''
function submit() {
let data = new FormData()
data.append('imgName', fileName)
data.append('img', file)
axios({
method: 'post',
timeout: 2000,
url: 'http://localhost:3000/postApi',
data: data
})
.then(response => {
console.log(response.data)
})
.catch(error => {
console.log(error)
})
}
function changeImg(e) {
file = e.target.files.item(0)
// 如果不选择图片
if (file === null) {
return
}
fileName = file.name
}
</script>
</body>
</html>
后端部分
这是本文要介绍的重点,为了用高效流畅的方式来解析文件上传请求,我们先引入formidable
库:
npm install formidable --save
formidable的流式解析器
让它成为了处理文件上传的绝佳选择,也就是说它能随着数据块的上传接收它们,解析它们,并吐出特定的部分,相信熟悉流的朋友会很好理解。这种方式不仅快,还不会因为需要大量缓冲而导致内存膨胀,即便像视频这种大型文件,也不会把进程压垮。
首先,我们在根目录下创建myImage文件,用于存放上传的图片(注意:如果没有创建,会导致上传报错),接着,我们创建一个IncomingForm实例form,并且设置存放路径为myImage文件夹。代码如下:
var http = require('http')
var formidable = require('formidable')
var server = http.createServer(function(req, res){
// 1 设置cors跨域
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
res.setHeader('Content-Type', 'application/json')
// 2
switch (req.method) {
case 'OPTIONS':
res.statusCode = 200
res.end()
break
case 'POST':
upload(req, res)
break
}
})
function upload(req, res) {
// 1 判断
if (!isFormData(req)) {
res.statusCode = 400
res.end('错误的请求, 请用multipart/form-data格式')
return
}
// 2 处理
var form = new formidable.IncomingForm()
form.uploadDir = './myImage'
form.keepExtensions = true
form.on('field', (field, value) => {
console.log(field)
console.log(value)
})
form.on('end', () => {
res.end('上传完成!')
})
form.parse(req)
}
function isFormData(req) {
let type = req.headers['content-type'] || ''
return type.includes('multipart/form-data')
}
server.listen(3000)
console.log('port is on 3000.')
用node app
开启http服务器后,在前端页面中上传一张kitty.jpg
,我们看到控制台打印出了前端上传的imgName属性:kitty.jpg
并且,myImage文件夹目录下多了一张图片:
打开一看,正是从前端上传的那张kitty.jpg
文件改名
我们发现,这个默认的文件名称并不是我们想要的,我们想改成以当前时间戳命名的文件,添加的功能代码如下:
var fs = require('fs')
form.on('file', (name, file) => {
// 重命名文件
let types = file.name.split('.')
let suffix = types[types.length - 1]
fs.renameSync(file.path, './myImage/' + new Date().getTime() + '.' + suffix)
})
再次上传,发现现在存的照片名称已经变成我们想要的格式了。
添加上传进度
Formidable的progress事件能给出收到的字节数,以及期望收到的字节数。我们可以借助这个做出一个进度条。
我们为上面的程序添加下面的代码,每次有progress事件激发,就会计算百分比并用console.log()输出:
form.on('progress', (bytesReceived, bytesExpected) => {
var percent = Math.floor(bytesReceived / bytesExpected * 100)
console.log(percent)
})
再次上传一张图片,现在控制台已经会打印出进度显示了:
当然,一般情况下,我们是要把这个进度传回到用户的浏览器中去,这对于任何想要上传大型文件的程序来说是个很棒的特性,并且这是个很适合用Node完成的任务。比如说用WebSocket
协议,或者像Socket.IO这样的实时模块,关于Node中使用websocket,后面我会单独出一篇文章来介绍。
错误处理
任何时候都不要忘了对程序添加错误处理,如果你的程序在重要的时候崩掉了,可能轻则被老板打屁股,重则拉出去祭天。想象一下,如果用户上传的图片很大,并且用户的网络还很慢,那么上传的时间会超出前端代码中设置的请求超时时间2s,服务器就会崩掉,不信?我们来试一下。
首先,我选择了一张很大的图片,5M,并且用chrome浏览器将浏览器网络环境设置为slow 3g,设置方法如下:
f12打开开发者工具,在more tools--network conditions
点击上传,我们看见服务端控制台的信息如下,服务器崩掉了:
所以,最后我们加上了错误处理,代码如下:
// 加上错误处理,防止用户网络慢,或者取消上传,导致服务器崩掉
form.on('error', err => {
console.log(err)
res.statusCode = 500
res.end('服务器内部错误!')
})
小结
现在,相信你已经学会了如何用Node处理文件上传了,结合前面的那篇用Node提供静态文件服务的文章,你是不是能够自己摸索着去尝试做一些有趣的事情了呢?
参考阅读
本文转载于:猿2048https://www.mk2048.com/blog/blog.php?id=hbiij2jbh2j
用Node处理文件上传的更多相关文章
- Node.js 文件上传 cli tools
Node.js 文件上传 cli tools byte stream 断点续传 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- Node开发文件上传系统及向七牛云存储和亚马逊AWS S3的文件上传
背景起,有奏乐: 有伟人曰:学习技能的最好途径莫过于理论与实践相结合. 初学Node这货时,每每读教程必会Fall asleep. 当真要开发系统时,顿觉精神百倍,即便踩坑无数也不失斗志. 因为同团队 ...
- Node.js文件上传
Node.js express使用Multer实现文件上传html部分 <div> <h3>文件上传:</h3> 选择一个文件上传: <br/> < ...
- node+express实现文件上传功能
在进行node web开发时,我们可能经常遇到上传文件的问题,这一块如果我们没有经验,可能会遇到很多坑,下面我将跟大家分享一下,实现文件上传的一些方式. 一.node+express文件上传的常用方式 ...
- NodeJS+formidable实现文件上传加自动重命名
前述 本人node初学者,此前使用原生node实现文件上传时遇到了一些困难,只做到了.txt 和.png两中格式的文件可以正常上传,如果上传其他格式文件服务端保存的文件会无法正常打开,原因是对form ...
- node.js 在 Express4.0 框架使用 Connect-Busboy 实现文件上传
node.js下四种post提交数据的方式 今天说分享的是其中一种,就是上传文件. Express 4.0 以后,将功能原子化,高内聚,低耦合,独立出了很多中间件 今天主要分享文件上传 对于conne ...
- node应用通过multer模块实现文件上传
multer用于处理文件上传的nodejs中间件,主要跟express框架搭配使用,只支持表单MIME编码为multipart/form-data类型的数据请求. 如果要处理其他编码的表单数据可以通过 ...
- Node.js新手教程——怎样实现文件上传功能
作者:zhanhailiang 日期:2014-11-16 本文将介绍怎样使用Node.js实现文件上传功能. 1. 初始化项目信息:npm init [root@~/wade/nodejs/node ...
- node.js系列(实例):原生node.js+formidable模块实现简单的文件上传
/** * 原生node.js结合formidable模块实现图片上传改名 * @Author:Ghost * @Date:2016/07/15 * @description: * 1.引入模块htt ...
随机推荐
- if 、whitch、for、while
if 用于过程的判断 whitch用于值得判断 if { } else if { } else if //当此前的过程满足条件时,程序便不再判断其他过程,但是if{}if{}这样的写法程序会将每个过 ...
- Python——模块&包&异常
模块&包&异常 一. 模块 Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义(变量)和Python语句. 模块能定义函数 ...
- php 23种设计模型 - 访问者模式
访问者模式是一种行为型模式,访问者表示一个作用于某对象结构中各元素的操作.它可以在不修改各元素类的前提下定义作用于这些元素的新操作,即动态的增加具体访问者角色. 访问者模式利用了双重分派.先将访问者传 ...
- 打靶笔记-04-vulnhub-Jangow
打靶笔记-04-vulnhub-Jangow 前面两篇名称写成了vulhub,已经更改为vulnhub;vulhub的之后再找个时间集中打一遍. 一.靶机信息 Name: Jangow: 1.0.1 ...
- Android 12(S) 图形显示系统 - BufferQueue的工作流程(十)
题外话 疫情隔离在家,周末还在努力学习的我 ..... 一.前言 上一篇文章中,有基本讲清楚Producer一端的处理逻辑,最后也留下了一个疑问: Consumer是什么时候来消费数据的?他是自己主 ...
- (九)React Ant Design Pro + .Net5 WebApi:后端环境搭建-IdentityServer4-简单配置
一.简介 IdentityServer4 是用于 ASP.NET Core 的 OpenID Connect 和 OAuth 2.0 框架,通过中间件的方式集成.JWT(json web token) ...
- ADT环境搭建手册
前言 笔者在搭建ADT环境之前一脸懵逼,甚至不知道ADT是什么,更别说与之相关的SDK.eclipse等,相信很多小伙伴跟我一样也是一脸茫然,所以在搭建环境之前有必要先了解一下它们是什么,有什么样的关 ...
- Prim算法求最小生成树
首先在介绍这个算法之前我们要之明确一下什么是最小生成树的概念: 由 V 中的全部 n 个顶点和 E 中 n−1 条边构成的无向连通子图被称为 G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 ...
- mmap代替通用IO读取文件数据(curious)
提供一份测试demo: #include <stdio.h> #include <string.h> #include <stdlib.h> #include &l ...
- kvm管理查看信息,添加,删除,暂停恢复,克隆等
KVM virsh管理指令 virsh 查看帮助信息 查看命令帮助 [root@KVM ~]# virsh Welcome to virsh, the virtualization interacti ...