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教程之异步I/O
Nov 21 NodeJs
NodeJS与HTML5相结合实现拖拽多个文件上传到服务器的实现方法
Jul 26 NodeJs
使用nodejs中httpProxy代理时候出现404异常的解决方法
Aug 15 NodeJs
NodeJS遍历文件生产文件列表功能示例
Jan 22 NodeJs
nodejs操作mysql实现增删改查的实例
May 28 NodeJs
详解Nodejs之静态资源处理
Jun 05 NodeJs
NodeJS收发GET和POST请求的示例代码
Aug 25 NodeJs
Mac下通过brew安装指定版本的nodejs教程
May 17 NodeJs
Nodejs中获取当前函数被调用的行数及文件名详解
Dec 12 NodeJs
用Electron写个带界面的nodejs爬虫的实现方法
Jan 29 NodeJs
Nodejs实现用户注册功能
Apr 14 NodeJs
nodejs的安装使用与npm的介绍
Sep 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 获取全局变量的代码
2011/04/21 PHP
PHP仿博客园 个人博客(2) 数据库增添改删
2013/07/05 PHP
改写ThinkPHP的U方法使其路由下分页正常
2014/07/02 PHP
PHP中创建图像并绘制文字的例子
2014/11/19 PHP
js DOM 元素ID就是全局变量
2012/09/20 Javascript
JS中类或对象的定义说明
2014/03/10 Javascript
在线引用最新jquery文件的实现方法
2016/08/26 Javascript
JavaScript之Vue.js【入门基础】
2016/12/06 Javascript
d3.js中冷门却实用的内置函数总结
2017/02/04 Javascript
Node.js 中exports 和 module.exports 的区别
2017/03/14 Javascript
使用JavaScript进行表单校验功能
2017/08/01 Javascript
javascript如何用递归写一个简单的树形结构示例
2017/09/06 Javascript
vue-awesome-swiper滑块插件使用方法详解
2017/11/27 Javascript
vue2.0实现音乐/视频播放进度条组件
2018/06/06 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
2018/08/03 Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
2018/12/06 jQuery
jQuery实现input[type=file]多图预览上传删除等功能
2019/08/02 jQuery
JS面向对象编程实现的Tab选项卡案例详解
2020/03/03 Javascript
Python处理RSS、ATOM模块FEEDPARSER介绍
2015/02/18 Python
Python自动发邮件脚本
2017/03/31 Python
在Django下创建项目以及设置settings.py教程
2019/12/03 Python
Python re正则表达式元字符分组()用法分享
2020/02/10 Python
全球性的在线时尚男装零售商:boohooMAN
2016/12/17 全球购物
英国领先的鞋类零售商和顶级品牌的官方零售商:Wynsors
2020/02/17 全球购物
10条PHP编程习惯
2014/05/26 面试题
测绘工程专业个人自我评价
2013/12/01 职场文书
婚假请假条怎么写
2014/04/10 职场文书
《水乡歌》教学反思
2014/04/24 职场文书
美术学专业求职信
2014/07/23 职场文书
关于环保的活动方案
2014/08/25 职场文书
房屋授权无偿使用证明
2014/11/29 职场文书
党员自评材料范文
2014/12/17 职场文书
齐云山导游词
2015/02/06 职场文书
美丽人生观后感
2015/06/03 职场文书
教师培训学习心得体会
2016/01/21 职场文书
纪检干部学习心得体会
2016/01/23 职场文书