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极简入门教程(一):模块机制
Oct 25 NodeJs
轻松创建nodejs服务器(3):代码模块化
Dec 18 NodeJs
Nodejs 获取时间加手机标识的32位标识实现代码
Mar 07 NodeJs
深入浅析Nodejs的Http模块
Jun 20 NodeJs
NodeJS链接MySql数据库的操作方法
Jun 27 NodeJs
Windows下快速搭建NodeJS本地服务器的步骤
Aug 09 NodeJs
NodeJS设计模式总结【单例模式,适配器模式,装饰模式,观察者模式】
Sep 06 NodeJs
NodeJS 中Stream 的基本使用
Jul 30 NodeJs
NodeJs操作MongoDB教程之分页功能以及常见问题
Apr 09 NodeJs
Nodejs异步流程框架async的方法
Jun 07 NodeJs
如何利用nodejs实现命令行游戏
Nov 24 NodeJs
nodejs利用readline提示输入内容实例代码
Jul 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处理斐波那契数列非递归方法
2012/02/04 PHP
php多任务程序实例解析
2014/07/19 PHP
php中字符串和正则表达式详解
2014/10/23 PHP
thinkphp的静态缓存用法分析
2014/11/29 PHP
在Javascript中定义对象类别
2006/12/22 Javascript
仅IE6/7/8中innerHTML返回值忽略英文空格的问题
2011/04/07 Javascript
关于二级域名下使用一级域名下的COOKIE的问题
2011/11/07 Javascript
web开发人员学习jQuery的6大理由及jQuery的优势介绍
2013/01/03 Javascript
Jquery中使用setInterval和setTimeout的方法
2013/04/08 Javascript
js 用CreateElement动态创建标签示例
2013/11/20 Javascript
使用jQuery重置(reset)表单的方法
2014/05/05 Javascript
javascript实现复选框超过限制即弹出警告框的方法
2015/02/25 Javascript
seajs加载jquery时提示$ is not a function该怎么解决
2015/10/23 Javascript
通过button将form表单的数据提交到action层的实例
2017/09/08 Javascript
Vue 通过自定义指令回顾v-内置指令(小结)
2018/09/03 Javascript
express.js中间件说明详解
2019/03/19 Javascript
Layui tree 下拉菜单树的实例代码
2019/09/21 Javascript
vue中使用v-for时为什么不能用index作为key
2020/04/04 Javascript
vue用elementui写form表单时,在label里添加空格操作
2020/08/13 Javascript
[02:44]DOTA2英雄基础教程 魅惑魔女
2014/01/07 DOTA
Python获取运行目录与当前脚本目录的方法
2015/06/01 Python
Python微医挂号网医生数据抓取
2019/01/24 Python
Django认证系统实现的web页面实现代码
2019/08/12 Python
python爬虫-模拟微博登录功能
2019/09/12 Python
python栈的基本定义与使用方法示例【初始化、赋值、入栈、出栈等】
2019/10/24 Python
Pytorch Tensor基本数学运算详解
2019/12/30 Python
基于python实现判断字符串是否数字算法
2020/07/10 Python
python实现马丁策略的实例详解
2021/01/15 Python
英国第二大营养品供应商:Vitabiotics
2016/10/01 全球购物
资产评估专业学生的自我鉴定
2013/11/14 职场文书
会展中心部门工作职责
2013/11/27 职场文书
降消项目实施方案
2014/03/30 职场文书
暑假社会实践证明格式
2014/10/28 职场文书
敲诈同学钱财检讨书范文
2014/11/18 职场文书
小学班主任研修日志
2015/11/13 职场文书
2019年国庆祝福语(70句)
2019/09/19 职场文书