美文网首页WEB前端开发技术杂谈
在Express中使用multer上传文件

在Express中使用multer上传文件

作者: BigDipper | 来源:发表于2018-10-22 18:58 被阅读14次

    参考地址

    概述

    上传文件是web开发中经常要用到的功能。这篇文章就是介绍在Express中如何使用multer中间件进行文件上传。

    使用的技术栈

    • 后台框架:Express
    • 上传中间件:multer
    • 前端异步操作:fetch接口

    开发过程

    1. 先把项目构造出来

    首先用一行代码,把环境搭起来。

    npm install --save express multer
    

    然后新建项目的入口文件app.js,代码如下:

    const path = require('path')
    const express = require('express');
    const app = express();
    
    // 静态化资源
    
    app.use(express.static(path.join(__dirname, 'public')))
    
    app.get('/', (req, res) => {
        res.send('首页');
    });
    
    app.listen(3000, () => console.log('服务器已启动!'));
    

    在命令行启动项目,在浏览器中就可以看到首页面:

    node app
    
    首页面.png

    2. 引入前端用到的上传页面和脚本

    之后新建index.htmldemo.js文件,目录结构,如图所示:

    目录结构.png

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>首页</title>
    </head>
    <body>
        <input type="file" id="myFile"/>
        <script src="/js/demo.js"></script>
    </body>
    </html>
    

    demo.js(为演示方便,代码并没有考虑fetch的兼容性问题):

    document.querySelector('#myFile').onchange = event => {
        const e = event || window.event;
        const target = e.target || e.srcElement;
        const file = target.files[0];
        const formdata = new FormData();
    
        formdata.append('myFile', file);    // 添加上传的文件对象
        
        fetch('/upload', {                  // 上传路径
            method: 'POST',
            body: formdata,
        })
        .then(res => res.json())
        .then(res => alert(res.message))
        .catch(err => console.dir(err));  
    };
    

    这时我们再回头来修改app.js的首页路由代码,以加载index.html页面:

    const fs = require('fs');
    
    app.get('/', (req, res) => {
        const html = fs.readFileSync('./view/index.html', { encoding: 'utf8' });  // 加载进行上传操作的页面
    
        res.send(html);
    });
    

    此时,首页如图所示:


    引入前端资源.png

    3. 用multer吧

    好了,重头戏来了。

    为了出彩,我们必须要修改一下app.js了,把multer模块引进来,并用它来接收上传的文件。光说不练,瞎扯淡,少废话,先上代码:

    const fs = require('fs');
    const path = require('path')
    const express = require('express');
    const multer = require('multer');
    const app = express();
    
    const storage = multer.diskStorage({        // 设置multer参数,个性化指定上传目录和文件名
        destination: (req, file, cb) => {
            const uploadFloder = './myUpload';  // 保存上传文件的目录
    
            try {
                fs.accessSync(uploadFloder);
            } catch (error) {
                fs.mkdirSync(uploadFloder);
            }
    
            cb(null, uploadFloder);
        },
        filename: (req, file, cb) => {
            cb(null, file.originalname);
        }
    });
    const upload = multer({                     // 实例化multer对象
        storage: storage
    });
    
    // 静态化资源
    
    app.use(express.static(path.join(__dirname, 'public')))
    
    app.get('/', (req, res) => {
        const html = fs.readFileSync('./view/index.html', { encoding: 'utf8' });  // 进行上传操作的页面
    
        res.send(html);
    });
    
    // 响应上传请求
    
    app.post('/upload', upload.single('myFile'), (req, res) => {
        res.send({
            message: '响应了请求'
        });
    });
    
    app.listen(3000, () => console.log('服务器已启动!'));
    

    这样就可以保存上传的文件了,有图有真相:


    上传文件和响应状态.png

    项目的结构:


    上传的文件.png

    好了,上传成功了,真相图也看了,现在该讲讲上面这些代码都是干什么用的了。

    const multer = require('multer');
    

    引入multer中间件。

    const storage = multer.diskStorage({        // 设置multer参数,个性化指定上传目录和文件名
        destination: (req, file, cb) => {
            const uploadFloder = './myUpload';  // 保存上传文件的目录
    
            try {
                fs.accessSync(uploadFloder);
            } catch (error) {
                fs.mkdirSync(uploadFloder);
            }
    
            cb(null, uploadFloder);
        },
        filename: (req, file, cb) => {
            cb(null, file.originalname);
        }
    });
    

    在此处进行个性化的设置,指定上传的目录和文件名。这一步并不是必须要做的。如果不设置,则生成的文件名是一个哈希值。

    const upload = multer({                     // 实例化multer对象
        storage: storage
    });
    

    使用刚才的设置来实例化对象。如果不个性化设置,则必须要使用dest属性来指定上传的路径,就像这样:

    const upload = multer({                     // 实例化multer对象
        dest: './myUpload'                        // 保存上传文件的目录
    });
    
    app.post('/upload', upload.single('myFile'), (req, res) => {
        res.send({
            message: '响应了请求'
        });
    });
    

    使用single()方法来响应单文件上传操作。注意:此处的myFile参数是前端上传的文件名,必须要一致。


    基因突变

    如何上传多个文件?

    上面的例子演示了单文件的上传操作,那么能不能同时上传多个文件呢?那肯定是能啊,只要把single()方法换成array(文件名, 最大文件个数)就行了。

    首先,我们先向页面添加multiple属性,使其支持多文件上传:

    <input type="file" id="myFile" multiple="multiple" />
    

    然后修改demo.js文件,将上传的多个文件放入formdata中,这些文件都使用同一个文件名myFile,代码如下:

    document.querySelector('#myFile').onchange = event => {
        const e = event || window.event;
        const target = e.target || e.srcElement;
        const files = target.files;
        const formdata = new FormData();
    
       for (const file of files) {
    
            // 添加上传的文件对象
            // formdata的append()方法有一个特点,
            // 它会把新值添加到已有值集合的后面,而不会用新值覆盖已有的值。
            // 这样就能达到用同一文件名,添加多个文件的目地。
    
            formdata.append('myFile', file);
        }
        
        fetch('/upload', {  // 上传文件
            method: 'POST',
            body: formdata,
        })
        .then(res => res.json())
        .then(res => alert(res.message))
        .catch(err => console.dir(err));  
    };
    

    最后,修改app.js文件,使用array()方法保存上传的多个文件,修改如下:

    app.post('/upload', upload.array('myFile', 10), (req, res) => {
        res.send({
            message: '响应了请求'
        });
    });
    

    就是这么简单,就是这么拉风。

    相关文章

      网友评论

        本文标题:在Express中使用multer上传文件

        本文链接:https://www.haomeiwen.com/subject/cjnuzftx.html