Nodejs文件上传、监听上传进度的代码


Posted in NodeJs onMarch 27, 2020

前言

文件上传如果加上进度条会有更好的用户体验(尤其是中大型文件),本文使用 Nodejs 配合前端完成这个功能。

前端我们使用 FormData 来作为载体发送数据。

效果 

Nodejs文件上传、监听上传进度的代码 

前端部分

HTML 部分 和 Js 部分

<input type="file" id="file" />
<!-- 进度条 -->
<progress id="progress" value="0" max="100"></progress>
// 获取 input file 的 dom 对象
const inputFile = document.querySelector('#file');

// 监听 change 事件
inputFile.addEventListener('change', function() {
 // 使用 formData 装载 file
 const formData = new FormData();
 formData.append('file', this.files[0]);
 
 // 上传文件
 upload(formData);
})

下面我们实现 upload 方法。

使用 XMLHttpRequest 的方式

const upload = ( formData ) => {
 const xhr = new XMLHttpRequest();
 // 监听文件上传进度
 xhr.upload.addEventListener('progress', function(e) {
 if (e.lengthComputable) {
 // 获取进度
 const progress = Math.round((e.loaded * 100) / e.total);
 
 document.querySelector('#progress').setAttribute('value', progress);
 }
 },false);
 
 // 监听上传完成事件
 xhr.addEventListener('load', ()=>{
 console.log(':smile:上传完成')
 }, false);
 
 xhr.open('post', 'http://127.0.0.1:3000/upload');
 xhr.send(formData); 
}

使用 jQuery 的 ajax 上传

jQuery 目前的使用量依然庞大,那么使用 jQuery 的 ajax 如何监听文件上传进度呢:

const upload = ( formData ) => {
 $.ajax({
 type: 'post',
 url: 'http://127.0.0.1:3000/upload',
 data: formData,
 // 不进行数据处理和内容处理
 processData: false,
 contentType: false,
 // 监听 xhr
 xhr: function() {
  const xhr = $.ajaxSettings.xhr();
  if (xhr.upload) {
  xhr.upload.addEventListener('progress', e => {
  const { loaded, total } = e;
  var progress = (loaded / total) * 100;
  document.querySelector('#progress').setAttribute('value', progress);
  },
  false
  );
  return xhr;
  }
 },
 success: function(response) {
  console.log('上传成功');
 }
 });
}

使用 axios 上传并监听进度

axios 使用量非常大,用它监听文件上传更简单,代码如下:

const upload = async ( formData ) => {

 let config = {
 // 注意要把 contentType 设置为 multipart/form-data
 headers: {
  'Content-Type': 'multipart/form-data'
 },
 
 // 监听 onUploadProgress 事件
 onUploadProgress: e => {
  const {loaded, total} = e;
  // 使用本地 progress 事件
  if (e.lengthComputable) {
  let progress = loaded / total * 100;
  document.querySelector('#progress').setAttribute('value', progress);
  }
 }
 };

 const { status } = await axios.post('http://127.0.0.1:3000/upload', formData, config);
 if (res.status === 200) {
  console.log('上传完成:grinning:');
 }
}

Nodejs 部分

这部分比较简单,其实就是单纯的文件上传,我们用 Koa 来实现.

环境搭建及依赖包安装

这里使用 koa2 ,安装以下依赖包:

  • koa
  • @koa/router: koa 的路由
  • @koa/cors:用于跨域
  • koa-body: 解析 body 数据
  • nodemon: 使用它启动服务,带有热更新

代码部分

const Koa = require('koa');
const Router = require('@koa/router');
const koaBody = require('koa-body');
const path = require('path');
const fs = require('fs');
const cors = require('@koa/cors');

const app = new Koa();
const router = new Router();

router.all('/upload', async ctx => {
 // 处理文件上传 
 const res = await dealFile(ctx);

 res && (ctx.body = {
 status: 200,
 msg: 'complete'
 });
});

// 中间件部分
app.use(cors());
app.use(
 koaBody({
 multipart: true,
 formidable: {
 maxFileSize: 2000 * 1024 * 1024 //最大2G
 }
 })
);
app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3000);

dealFile 方法处理上传的文件

出于性能考虑,操作 file 毫无疑问要使用 stream 。

我们要监听文件流 end 事件,由于无法在事件回调里返回响应,因为会报 404,所以需要使用 Promise 来封装一下,然后用 async、await

const dealFile = ctx => {
 const { file } = ctx.request.files;

 const reader = fs.createReadStream(file.path);
 const writer = fs.createWriteStream(
 // 文件上传到 image 文件夹中
 path.resolve(__dirname, './image', file.name)
 );

 return new Promise((resove, reject) => {
 
 reader.pipe(writer);
 
 reader.on('end', () => {
 resove(true);
 });
 
 reader.on('error', err => {
 throw err;
 })
 
 });
};

到这里就全部完成了。

这里注意一下:前端监听文件进度不需要后端有什么特殊处理,后端仅仅是做了文件流的写入而已。

总结

到此这篇关于Nodejs文件上传、监听上传进度的文章就介绍到这了,更多相关Nodejs文件上传、监听上传进度内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

NodeJs 相关文章推荐
nodejs实用示例 缩址还原
Dec 28 NodeJs
Nodejs中自定义事件实例
Jun 20 NodeJs
基于NodeJS的前后端分离的思考与实践(四)安全问题解决方案
Sep 26 NodeJs
详谈nodejs异步编程
Dec 04 NodeJs
NodeJS学习笔记之Connect中间件应用实例
Jan 27 NodeJs
Windows系统下使用Sublime搭建nodejs环境
Apr 13 NodeJs
Nodejs回调加超时限制两种实现方法
Jun 09 NodeJs
原生nodejs使用websocket代码分享
Apr 07 NodeJs
基于Nodejs的Tcp封包和解包的理解
Sep 19 NodeJs
nodejs log4js 使用详解
May 31 NodeJs
监控Nodejs的性能实例代码
Jul 02 NodeJs
图解NodeJS实现登录注册功能
Sep 16 NodeJs
nodejs如何在package.json中设置多条启动命令
Mar 16 #NodeJs
nodejs脚本centos开机启动实操方法
Mar 04 #NodeJs
nodejs制作小爬虫功能示例
Feb 24 #NodeJs
nodejs使用socket5进行代理请求的实现
Feb 21 #NodeJs
linux 下以二进制的方式安装 nodejs
Feb 12 #NodeJs
nodejs实现百度舆情接口应用示例
Feb 07 #NodeJs
使用nodeJS中的fs模块对文件及目录进行读写,删除,追加,等操作详解
Feb 06 #NodeJs
You might like
第五节--克隆
2006/11/16 PHP
php写的带缓存数据功能的mysqli类
2012/09/06 PHP
PHP设置图片文件上传大小的具体实现方法
2013/10/11 PHP
php构造函数实例讲解
2013/11/13 PHP
PHP反射机制用法实例
2014/08/28 PHP
Zend Framework教程之路由功能Zend_Controller_Router详解
2016/03/07 PHP
ie focus bug 解决方法
2009/09/03 Javascript
jQuery前台数据获取实现代码
2011/03/16 Javascript
JS实现鼠标单击与双击事件共存
2014/03/08 Javascript
PHP守护进程实例
2015/03/06 Javascript
基于javascript实现单选及多选的向右和向左移动实例
2015/07/25 Javascript
JavaScript中ES6 Babel正确安装过程
2016/07/18 Javascript
微信小程序 progress组件详解及实例代码
2016/10/25 Javascript
js实现无缝滚动图(可控制当前滚动的方向)
2017/02/22 Javascript
js实现放大镜特效
2017/05/18 Javascript
详解bootstrap用dropdown-menu实现上下文菜单
2017/09/22 Javascript
详解vue mixins和extends的巧妙用法
2017/12/20 Javascript
详解在React里使用&quot;Vuex&quot;
2018/04/02 Javascript
基于Vue2x实现响应式自适应轮播组件插件VueSliderShow功能
2018/05/16 Javascript
Vue使用axios出现options请求方法
2019/05/30 Javascript
layui数据表格实现重载数据表格功能(搜索功能)
2019/07/27 Javascript
JS常用排序方法实例代码解析
2020/03/03 Javascript
JavaScript语法约定和程序调试原理解析
2020/11/03 Javascript
python生成指定尺寸缩略图的示例
2014/05/07 Python
使用Python装饰器在Django框架下去除冗余代码的教程
2015/04/16 Python
在Python的Flask框架中使用日期和时间的教程
2015/04/21 Python
python获取当前日期和时间的方法
2015/04/30 Python
css3与html5实现响应式导航菜单(导航栏)效果分享
2014/02/12 HTML / CSS
四川成都导游欢迎词
2014/01/18 职场文书
高三学习决心书
2014/03/11 职场文书
岗位标兵事迹材料
2014/05/17 职场文书
优秀团员事迹材料1000字
2014/08/20 职场文书
工作证明范本(2篇)
2014/09/14 职场文书
学校党员个人问题整改措施思想汇报
2014/10/08 职场文书
MySQL时间盲注的五种延时方法实现
2021/05/18 MySQL
深入详解JS函数的柯里化
2021/06/09 Javascript