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教程 安装express及配置app.js文件的详细步骤
May 11 NodeJs
nodejs文件操作模块FS(File System)常用函数简明总结
Jun 05 NodeJs
14款NodeJS Web框架推荐
Jul 11 NodeJs
Nodejs全栈框架StrongLoop推荐
Nov 09 NodeJs
Nodejs学习item【入门手上】
May 05 NodeJs
NodeJS整合银联网关支付(DEMO)
Nov 09 NodeJs
Windows下使用Nodejs运行js的方法
Sep 02 NodeJs
nodejs中art-template模板语法的引入及冲突解决方案
Nov 07 NodeJs
使用nodejs+express实现简单的文件上传功能
Dec 27 NodeJs
nodejs简单读写excel内容的方法示例
Mar 16 NodeJs
nodejs实现百度舆情接口应用示例
Feb 07 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 判断网页是否是utf8编码的方法
2014/06/06 PHP
destoon找回管理员密码的方法
2014/06/21 PHP
PDO预处理语句PDOStatement对象使用总结
2014/11/20 PHP
php计算数组相同值出现次数的代码(array_count_values)
2015/01/20 PHP
详细解读php的命名空间(二)
2018/02/21 PHP
ThinkPHP3.2.3框架Memcache缓存使用方法实例总结
2019/04/15 PHP
如何确保JavaScript的执行顺序 之实战篇
2011/03/03 Javascript
了解一点js的Eval函数
2012/07/26 Javascript
一个不错的字符串转码解码函数(自写)
2014/07/31 Javascript
引用其它js时如何同时处理多个window.onload事件
2014/09/02 Javascript
用javascript关闭本窗口不弹出询问框的方法
2014/09/12 Javascript
关于vue面试题汇总
2018/03/20 Javascript
js定义类的方法示例【ES5与ES6】
2019/07/30 Javascript
AntV F2和vue-cli构建移动端可视化视图过程详解
2019/10/08 Javascript
vue keep-alive 动态删除组件缓存的例子
2019/11/04 Javascript
vue下canvas裁剪图片实例讲解
2020/04/16 Javascript
[02:44]完美大师赛主赛事淘汰赛第二日观众采访
2017/11/24 DOTA
python中的字典详细介绍
2014/09/18 Python
通过Python实现自动填写调查问卷
2017/09/06 Python
python实现Decorator模式实例代码
2018/02/09 Python
numpy.delete删除一列或多列的方法
2018/04/03 Python
python Qt5实现窗体跟踪鼠标移动
2019/12/13 Python
pycharm下配置pyqt5的教程(anaconda虚拟环境下+tensorflow)
2020/03/25 Python
聊聊python中的循环遍历
2020/09/07 Python
Python中读取文件名中的数字的实例详解
2020/12/25 Python
探讨HTML5移动开发的几大特性(必看)
2015/12/30 HTML / CSS
欧洲最大的化妆品连锁公司:Douglas道格拉斯
2017/05/06 全球购物
以特惠价提供在线奢侈品购物:FRMODA.com
2018/01/25 全球购物
Nip + Fab官网:英国美容品牌
2019/08/26 全球购物
在加拿大在线租赁和购买电子游戏:Game Access
2019/09/02 全球购物
《狮子和兔子》教学反思
2014/03/02 职场文书
二手房购房意向书范本
2014/04/01 职场文书
保护校园环境倡议书
2015/04/28 职场文书
RPM包方式安装Oracle21c的方法详解
2021/08/23 Oracle
asyncio异步编程之Task对象详解
2022/03/13 Python
CSS list-style-type属性使用方法
2023/05/21 HTML / CSS