如何在Node.js和Express中上传文件

2020-10-26 17:34:36 浏览数 (1)

大量的移动应用程序和网站允许用户上传个人资料图片和其他文件。 因此,在使用Node.js和Express构建REST API时,通常需要处理文件上传。

在本教程中,我们将讨论如何使用Node.js和Express后端处理单个和多个文件上传,以及如何将上传的文件保存在服务器上。

安装

首先,让我们通过运行以下命令来创建一个新的Node.js应用程序。 我正在使用npm进行软件包管理。 如果愿意,可以使用yarn

代码语言:javascript复制
# creat a new directory & switch to it
$ mkdir files-upload && cd files-upload

# run this for npm to create a new app
$ npm init -y

# run this for yarn to create a new app
$ yarn init -y 

-y--yes跳过交互会话,并根据默认设置生成package.json文件。 接下来,运行以下命令以安装必需的依赖项:

代码语言:javascript复制
# run this for npm
$ npm install express body-parser cors express-fileupload morgan lodash --save

# or using yarn
$ yarn add express body-parser cors express-fileupload morgan lodash 

以下是上述每个软件包的功能:

  • express-基于Node.js构建的流行Web框架。 我们将使用它来开发REST API。
  • body-parser-Node.js请求主体解析中间件,该中间件在处理程序之前解析传入的请求主体,并使其在req.body属性下可用。 简而言之,它简化了传入请求。
  • cors-另一种Express中间件,用于启用CORS(跨域资源共享)请求。
  • express-fileupload-用于上传文件的Simple Express中间件。 它解析multipart/form-data请求,提取文件(如果有),并在req.files属性下使它们可用。
  • morgan-用于记录HTTP请求的Node.js中间件。
  • lodash-一个JavaScript库,为数组,数字,对象,字符串等提供实用程序功能。

创建Express服务器

安装所需的依赖项之后,让我们开始创建Express服务器。 index.js

代码语言:javascript复制
const express = require('express');
const fileUpload = require('express-fileupload');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const _ = require('lodash');

const app = express();

// enable files upload
app.use(fileUpload({
    createParentPath: true
}));

//add other middleware
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(morgan('dev'));

//start app 
const port = process.env.PORT || 3000;

app.listen(port, () => 
  console.log(`App is listening on port ${port}.`)
);

上面的代码很容易理解。 它首先设置express-fileupload中间件以启用multipart/form-data请求。 之后,添加了其他Express中间件以允许跨域资源共享(CORS),请求正文解析和HTTP请求日志记录。 最后,它将在端口3000上启动服务器。

上传单个文件

让我们创建第一个路由,该路由允许用户上传其个人资料图片。

代码语言:javascript复制
app.post('/upload-avatar', async (req, res) => {
    try {
        if(!req.files) {
            res.send({
                status: false,
                message: 'No file uploaded'
            });
        } else {
            //Use the name of the input field (i.e. "avatar") to retrieve the uploaded file
            let avatar = req.files.avatar;
            
            //Use the mv() method to place the file in upload directory (i.e. "uploads")
            avatar.mv('./uploads/'   avatar.name);

            //send response
            res.send({
                status: true,
                message: 'File is uploaded',
                data: {
                    name: avatar.name,
                    mimetype: avatar.mimetype,
                    size: avatar.size
                }
            });
        }
    } catch (err) {
        res.status(500).send(err);
    }
});

上面的代码段是一个HTTP POST函数。 当您向/upload-avatar路由发送multipart/form-data请求以上传文件时,此功能会将文件保存到服务器上的uploads文件夹中。

express-fileupload中间件如何工作?

它使上传的文件可从req.files属性访问。 例如,如果您上传名为my-profile.jpg的文件,并且您的字段名是avatar,则可以通过req.files.avatar访问它。 avatar对象将包含以下信息:

  • avatar.name-上传文件的名称,即my-profile.jpg
  • avatar.mv-将文件移动到服务器上其他位置的功能
  • avatar.mimetype-文件的mime类型
  • avatar.size-文件大小,以字节为单位
  • avatar.data-上载文件的缓冲区表示

上传多个文件

让我们开始创建另一条路由,以允许用户一次上传多张照片。

代码语言:javascript复制
app.post('/upload-photos', async (req, res) => {
    try {
        if(!req.files) {
            res.send({
                status: false,
                message: 'No file uploaded'
            });
        } else {
            let data = []; 
    
            //loop all files
            _.forEach(_.keysIn(req.files.photos), (key) => {
                let photo = req.files.photos[key];
                
                //move photo to uploads directory
                photo.mv('./uploads/'   photo.name);

                //push file details
                data.push({
                    name: photo.name,
                    mimetype: photo.mimetype,
                    size: photo.size
                });
            });
    
            //return response
            res.send({
                status: true,
                message: 'Files are uploaded',
                data: data
            });
        }
    } catch (err) {
        res.status(500).send(err);
    }
});

上面的代码与单文件上传非常相似,除了我们现在收到的是photos字段而不是avatar。 我们使用lodash实用程序函数(_.forEach()_.keysIn())遍历photos字段,然后将每张照片保存到uploads目录。

测试应用程序

我们快完成了! 在终端的项目根目录中运行以下命令以启动应用程序:

代码语言:javascript复制
$ node index.js

它将在端口3000上启动应用程序。让我们使用Postman发送HTTP multipart/form-data请求:

1. 单文件

2. 多个文件

如果您想使上传的文件可以从任何地方公开访问,只需将uploads目录设置为静态:

代码语言:javascript复制
app.use(express.static('uploads'));

现在,您可以直接在浏览器中打开上传的文件:

代码语言:javascript复制
http://localhost:3000/icon.png

文件大小限制

如果要限制一次上传的文件的大小,请将limits选项直接传递给express-fileupload中间件:

代码语言:javascript复制
app.use(fileUpload({
    createParentPath: true,
    limits: { 
        fileSize: 2 * 1024 * 1024 * 1024 //2MB max file(s) size
    },
}));

源代码:在MIT许可下从GitHub下载完整的源代码。

结论

那是所有! 我们学习了如何使用Node.js和Express框架上传单个和多个文件。 ·express-fileupload·是一种易于使用的Express中间件,用于处理文件上传。 查看其文档以获取更多配置选项。

如果您有任何疑问或反馈,请随时给我发送tweet。

快乐学习Node.js

0 人点赞