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框架Express的模板视图机制分析
Jul 19 NodeJs
Nodejs异步回调的优雅处理方法
Sep 25 NodeJs
用nodejs的实现原理和搭建服务器(动态)
Aug 10 NodeJs
nodejs学习笔记之路由
Mar 27 NodeJs
使用nodejs爬取前程无忧前端技能排行
May 06 NodeJs
nodejs操作mongodb的增删改查功能实例
Nov 09 NodeJs
windows系统下更新nodejs版本的方案
Nov 24 NodeJs
nodejs操作mongodb的填删改查模块的制作及引入实例
Jan 02 NodeJs
Nodejs 和 Electron ubuntu下快速安装过程
May 04 NodeJs
详解webpack打包nodejs项目(前端代码)
Sep 19 NodeJs
详解NodeJS模块化
Jun 15 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中通过加号合并数组的一个简单方法分享
2011/01/27 PHP
PHP中改变图片的尺寸大小的代码
2011/07/17 PHP
PHP分页详细讲解(有实例)
2013/10/30 PHP
php session劫持和防范的方法
2013/11/12 PHP
php静态文件返回304技巧分享
2015/01/06 PHP
php实现求相对时间函数
2015/06/15 PHP
详解ThinkPHP3.2.3验证码显示、刷新、校验
2016/12/29 PHP
CI框架附属类用法分析
2018/12/26 PHP
使用js在页面中绘制表格核心代码
2013/09/16 Javascript
jQuery中:input选择器用法实例
2015/01/03 Javascript
结合代码图文讲解JavaScript中的作用域与作用域链
2016/07/05 Javascript
类似于QQ的右滑删除效果的实现方法
2016/10/16 Javascript
jQuery图片切换动画特效
2016/11/02 Javascript
详解Node.js项目APM监控之New Relic
2017/05/12 Javascript
AngularJS实现自定义指令及指令配置项的方法
2017/11/20 Javascript
Vue 拦截器对token过期处理方法
2018/01/23 Javascript
JS实现多功能计算器
2020/10/28 Javascript
Python实现Tab自动补全和历史命令管理的方法
2015/03/12 Python
常见的在Python中实现单例模式的三种方法
2015/04/08 Python
Python实现树莓派WiFi断线自动重连的实例代码
2017/03/16 Python
python使用tensorflow深度学习识别验证码
2018/04/03 Python
Python学习笔记之pandas索引列、过滤、分组、求和功能示例
2019/06/03 Python
css3实现冲击波效果的示例代码
2018/01/11 HTML / CSS
美国最大网上鞋店:Zappos
2016/07/25 全球购物
Europcar英国:英国汽车和货车租赁
2017/01/21 全球购物
精选奢华:THE LIST
2019/09/05 全球购物
酒店总经理工作职责
2013/12/13 职场文书
文明宿舍获奖感言
2014/02/07 职场文书
运动会跳远加油稿
2014/02/20 职场文书
《美丽的公鸡》教学反思
2014/02/25 职场文书
HR求职自荐信范文
2014/06/21 职场文书
学校感恩教育活动总结
2014/07/07 职场文书
领导班子群众路线与四风问题对照检查材料思想汇报
2014/10/11 职场文书
瘦西湖导游词
2015/02/03 职场文书
Python Django 后台管理之后台模型属性详解
2021/04/25 Python
Python自动化工具之实现Excel转Markdown表格
2022/04/08 Python