当前位置:首页 > 技术分析 > 正文内容

Nodejs文件上传、监听上传进度(node实现文件上传)

ruisui884个月前 (02-03)技术分析21

文件上传如果加上进度条会有更好的用户体验(尤其是中大型文件),本文使用Nodejs配合前端完成这个功能。

前端我们使用 FormData 来作为载体发送数据。

效果

前端部分

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('上传完成')
    }, 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('上传完成');
      }
}

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;
    })
    
  });
};

到这里就全部完成了。

这里注意一下:前端监听文件进度不需要后端有什么特殊处理,后端仅仅是做了文件流的写入而已。


作者:Ve
链接:https://juejin.im/post/5e7ca27df265da42ac0294e5
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/1118.html

标签: nodejs更新
分享给朋友:

“Nodejs文件上传、监听上传进度(node实现文件上传)” 的相关文章

医疗养老收费管理系统

医疗养老收费管理系统headerfooter《医疗养老收费管理系统》是最新开发的适用于养老保险收费行业的管理系统。主要功能:1.基本信息:单位设置、缴费基数、缴费比例和队别设置;2.医疗保险管理:医疗保险人员信息、医疗保险收费、医疗保险信息查询、医疗保险收费查询、医疗保险收费情况;3.养老保险信息:...

继Yuzu后,任天堂要求移除多个Switch模拟器项目

IT之家 7 月 11 日消息,任天堂美国分公司 (Nintendo of America) 已要求移除多个用于模拟 Nintendo Switch 游戏的开源模拟器项目,其中包括 Suyu、Nzu、Uzuy、Torzu、Sudachi 和 Yuzu-vanced 等。这些模拟器均被指控包含绕过任天...

7 招教你轻松搭建以图搜图系统

作者 | 小龙责编 | 胡巍巍当您听到“以图搜图”时,是否首先想到了百度、Google 等搜索引擎的以图搜图功能呢?事实上,您完全可以搭建一个属于自己的以图搜图系统:自己建立图片库;自己选择一张图片到库中进行搜索,并得到与其相似的若干图片。Milvus 作为一款针对海量特征向量的相似性检索引擎,旨在...

有效地简化导航-Part 1:信息架构

「四步走」——理想的导航系统要做一个可用的导航系统,网页设计师必须按顺序回答以下4个问题:1. 如何组织内容?2. 如何解释导航的选项?3. 哪种导航菜单最适合容纳这些选项?4. 如何设计导航菜单?前两个问题关注构建和便签内容,通常称为信息架构。信息架构师通常用网站地图(site map diagr...

22《Vue 入门教程》VueRouter 路由嵌套

1. 前言本小节我们介绍如何嵌套使用 VueRouter。嵌套路由在日常的开发中非常常见,如何定义和使用嵌套路由是本节的重点。同学们在学完本节课程之后需要自己多尝试配置路由。2. 配置嵌套路由实际项目中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层...

TDesign企业级开源设计系统越发成熟稳定,支持 Vue3 / 小程序

TDesing 发展越来越好了,出了好几套组件库,很成熟稳定了,新项目完全可以考虑使用。早在2021年,腾讯的 TDesing 刚发布不久,我就写了一篇简短的文章来介绍,当时主要关注的是 TDesign 的 Vue 组件库和用来搭建 admin 后台系统的实用性。虽然当时看起来不错,但还处于测试版,...