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的10个性能优化技巧
Jul 15 NodeJs
nodejs中实现sleep功能实例
Mar 24 NodeJs
nodejs爬虫抓取数据乱码问题总结
Jul 03 NodeJs
nodejs入门教程五:连接数据库的方法分析
Apr 24 NodeJs
nodejs multer实现文件上传与下载
May 10 NodeJs
浅谈NodeJs之数据库异常处理
Oct 25 NodeJs
nodejs实现简单的gulp打包
Dec 21 NodeJs
nodejs log4js 使用详解
May 31 NodeJs
NodeJs实现简易WEB上传下载服务器
Aug 10 NodeJs
NodeJS模块Buffer原理及使用方法解析
Nov 11 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
关于PHP中的Class的几点个人看法
2006/10/09 PHP
PHP 检查扩展库或函数是否可用的代码
2010/04/06 PHP
PHP取余函数介绍MOD(x,y)与x%y
2014/05/15 PHP
PHP ajax 异步执行不等待执行结果的处理方法
2015/05/27 PHP
php中session_id()函数详细介绍,会话id生成过程及session id长度
2015/09/23 PHP
php in_array() 检查数组中是否存在某个值详解
2016/11/23 PHP
php实现姓名根据首字母排序的类与方法(实例代码)
2018/05/16 PHP
PHP实现获取文件mime类型多种方法解析
2020/05/28 PHP
JavaScript 三种创建对象的方法
2009/10/16 Javascript
基于jquery的设置页面文本框 只能输入数字的实现代码
2011/04/19 Javascript
自定义刻度jQuery进度条及插件
2015/09/02 Javascript
JS实现浏览器状态栏显示时间的方法
2015/10/27 Javascript
AngularJS入门心得之directive和controller通信过程
2016/01/25 Javascript
微信小程序 视图层(xx.xml)和逻辑层(xx.js)详细介绍
2016/10/13 Javascript
xmlplus组件设计系列之分隔框(DividedBox)(8)
2017/05/02 Javascript
JS中跳出循环的示例代码
2017/09/14 Javascript
基于webpack 实用配置方法总结
2017/09/28 Javascript
vue.js中npm安装教程图解
2018/04/10 Javascript
微信小程序页面间传值与页面取值操作实例分析
2019/04/30 Javascript
在layui中对table中的数据进行判断(0、1)转换为提示信息的方法
2019/09/28 Javascript
Vue 实现分页与输入框关键字筛选功能
2020/01/02 Javascript
Vue3+elementui plus创建项目的方法
2020/12/01 Vue.js
浅谈Python2获取中文文件名的编码问题
2018/01/09 Python
python Matplotlib底图中鼠标滑过显示隐藏内容的实例代码
2019/07/31 Python
Python中typing模块与类型注解的使用方法
2019/08/05 Python
Python使用微信itchat接口实现查看自己微信的信息功能详解
2019/08/22 Python
python GUI库图形界面开发之PyQt5单选按钮控件QRadioButton详细使用方法与实例
2020/02/28 Python
python+openCV对视频进行截取的实现
2020/11/27 Python
将n个数按输入顺序的逆序排列,用函数实现
2012/11/14 面试题
新闻专业本科生的自我评价分享
2013/11/20 职场文书
求职简历的自我评价
2014/01/31 职场文书
辩论赛主持词
2014/03/18 职场文书
2014乡镇干部对照检查材料思想汇报
2014/09/26 职场文书
幼儿园中班教育随笔
2015/08/14 职场文书
Windows下redis下载、redis安装及使用教程
2021/06/02 Redis
JavaScript函数柯里化
2021/11/07 Javascript