Node.js与Express联合中间件express-fileupload使用axios实现文件上传

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.js与Express联合中间件express-fileupload使用axios实现文件上传相关的知识,希望对你有一定的参考价值。

概述

涉及技术栈:

  • Node.js:使用javascript处理后端逻辑。
  • Express:node.js的web框架。
  • express-fileupload:中间件,处理上传的文件。
  • axios:在前端发送POST请求。
  • body-parser:中间件,获取POST请求提交的数据。

Node.js与Express

使用Node.js结合Express搭建web环境。只需要两个文件:

upload-file.html:包含文件上传表单的html页面。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
<input type="file" name="avatar" id="avatar"><br/>
<button id="upload-button">上传</button>
<script>
    document.getElementById("upload-button").onclick = function () 
        console.log(document.getElementById("avatar").files[0]);
    
</script>
</body>
</html>

upload.js:启动node.js的express程序,并渲染upload-file.html文件,可通过http://127.0.0.1:8989/upload-file.html访问该页面来进行文件上传操作。注意,需要安装express包才能使用Express。

// 第一步,引入express
var express = require("express");

// 第二步,创建服务器应用程序,即原来的http.createServer()
var app = express();

// 渲染upload-file.html页面
app.get('/upload-file.html', function (request, response) 
    require('fs').readFile('./upload-file.html', function (err, data) 
        response.end(data);
    );
);

// 监听端口,相当于原来的server.listen()
app.listen(8989, function () 
    console.log("app is running at port 8989.");
);

express-fileupload中间件

安装

NPM官网:https://www.npmjs.com/package/express-fileupload
GitHub官网:https://github.com/richardgirges/express-fileupload

首先要先安装express-fileupload包:

# With NPM
npm i express-fileupload

# With Yarn
yarn add express-fileupload

注意:express-fileupload属于中间件,必须在Node.js下的express框架下使用。

使用

基本使用

安装完成还需要导入才能使用,所以按照下面的代码进行导入:

// 第一步,引入express
// var express = require("express");
// 引入文件上传模块express-fileupload
var fileUpload = require('express-fileupload');

// 第二步,创建服务器应用程序
// var app = express();
// 配置文件上传模块
app.use(fileUpload());

注意,注释掉的代码就是express环境。

接着就是使用了,通过request.files即可获取到上传的文件对象:

app.post('/upload',function (request, response) 
   console.log(request.files);
);

上传单个文件

首先准备一个表单:form-upload.html。form标签的三个属性如下:

  • action:表示处理上传文件的请求路径。
  • method:表示请求方式,必须是POST。
  • encType:上传文件必须指定的属性,值是multipart/form-data
<html>
<body>
<form action='http://localhost:8989/upload' method='post' encType="multipart/form-data">
    <input type="file" name="avatar"/>
    <input type='submit' value='上传'/>
</form>
</body>
</html>

接着在app.js中通过`request.files``获取上传的文件对象,注意在express环境下。

// 第一步,引入express
var express = require("express");
// 引入文件上传模块express-fileupload
var fileUpload = require('express-fileupload');

// 第二步,创建服务器应用程序
var app = express();
// 配置文件上传模块
app.use(fileUpload());

// 处理上传文件请求
app.post('/upload',function (request, response) 
   console.log(request.files);
);

// 监听端口8989,端口号自定义
app.listen(8989, function () 
    console.log("app is running at port 8989.");
);

控制台打印结果如下:


  avatar: 
    name: 'IMG1604419343790.jpg',
    data: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff db 00 43 00 0b 09 09 07 09 09 07 09 09 09 09 0b 09 09 09 09 09 09 0b 09 0b 0b 0c 0b 0b ... 53231 more bytes>,
    size: 53281,
    encoding: '7bit',
    tempFilePath: '',
    truncated: false,
    mimetype: 'image/jpeg',
    md5: '5d338cce6c4810989abb1bbe77529a98',
    mv: [Function: mv]
  

其中avatar就是input标签的name属性值,一一对应。所以如果我们要获取到上传文件的数据,即可:

  • request.files.avatar.name: 上传文件的名字。
  • request.files.avatar.data:上传文件数据,是一个Buffer,可以通过writeFile方法写入到本地文件中。
  • request.files.avatar.size:上传文件的大小,单位为字节。
  • request.files.avatar.tempFilePath:临时文件路径。
  • request.files.avatar.truncated:表示文件是否超过大小限制。
  • request.files.avatar.mimetype:文件的mimetype类型。
  • request.files.avatar.md5:文件的MD5值,可用于检验文件。
  • request.files.avatar.mv:将文件移动到服务器上其他位置的回调函数。

知道了上面的属性和方法,就可以进一步利用mv函数把上传的文件保存到指定位置:

// 第一步,引入express
var express = require("express");
// 引入文件上传模块express-fileupload
var fileUpload = require('express-fileupload');

// 第二步,创建服务器应用程序
var app = express();
// 配置文件上传模块
app.use(fileUpload());

app.post('/upload', function (request, response) 
    var avatarFile = request.files.avatar;
    console.log(avatarFile);
    // 处理文件上传失败
    if (!request.files || Object.keys(request.files).length === 0) 
        return response.status(400).send("没有文件被上传!")
    
    // 获取上传文件名
    var fileName = avatarFile.name;// 注意avatar对应input标签的name属性值
    // 设定文件的保存路径
    var uploadPath = __dirname + "/upload/img/" + fileName;
    // 使用mv方法来将上传文件保存到指定路径下
    // mv(filePath, callback)有两个参数:filePath指定是上传文件的保存路径,callback是回调函数用来处理判断是否上传成功并且有一个参数err表示错误对象
    avatarFile.mv(uploadPath, function (err) 
        if (err)
            return response.status(500).send(err);
        response.send('文件上传成功!');
    );
);

// 监听端口
app.listen(8989, function () 
    console.log("app is running at port 8989.");
);

注意:上传文件的保存目录一定要先创建,代码是不会自动给你创建的。如/upload/img必须现有这个目录才能上传成功,否则会上传失败。

上传多个文件

express-fileupload支持多个文件的上传。

准备一个可以上传多个文件的表单,如下:

<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
<form action='http://localhost:8989/upload' method='post' encType="multipart/form-data">
    <input type="file" name="my_file_one"/><br/>
    <input type="file" name="my_file_two"/><br/>
    <input type="file" name="my_file_three"><br/>
    <input type='submit' value='上传'/>
</form>
</body>
</html>

然后上传文件的处理逻辑也是类似的:

app.post('/upload', function (request, response) 
    console.log(request.files.my_file_one.name);
    console.log(request.files.my_file_two.name);
    console.log(request.files.my_file_three.name);
);

利用循环将多个文件保存到指定路径,代码如下:

// 第一步,引入express
var express = require("express");
// 引入文件上传模块express-fileupload
var fileUpload = require('express-fileupload');

// 第二步,创建服务器应用程序
var app = express();
// 配置文件上传模块
app.use(fileUpload());

app.post('/upload', function (request, response) 
    var files = request.files;
    for (var key in files) 
        var file = files[key];
        console.log('正在上传' + file.name + '...');
        // 设定文件的保存路径
        var uploadPath = __dirname + "/upload/img/" + file.name;
        file.mv(uploadPath, function (err) 
            if (err)
                return response.status(500).send(err);
        )
    
    response.send("上传成功!");
);

// 监听端口
app.listen(8989, function () 
    console.log("app is running at port 8989.");
);

使用axios提交数据上传文件

单独上传文件

这次我们就不使用表单来上传文件了,而是使用axios发送Ajax请求来上传文件。准备一个upload-file.html并且引入axios.js:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<input type="file" name="avatar" id="avatar"><br/>
<button id="upload-button">上传</button>
<script>
    // 通过"上传"按钮触发点击事件
    document.getElementById("upload-button").onclick = function () 
        console.log(document.getElementById("avatar").files[0]);
        // 创建FormData对象
        var formData = new FormData();
        // 将图片添加到FormData对象中,其中"avatar"对应的是input标签中的name属性
        formData.append("avatar", document.getElementById("avatar").files[0]);
        // 发送POST请求上传文件
        axios(
            method: 'POST',
            url: '/upload',
            data: formData,
            headers: 
                // 必须修改请求头Content-Type为multipart/form-data才能上传文件
                "Content-Type": "multipart/form-data"
            
        ).then(function (response) 
        		 // 响应回来的数据
            console.log(response.data);
        ).catch(function (reason) 
            console.log(reason);
        )
    
</script>
</body>
</html>

其中headers属性值是必须的,因为设置了请求头的Content-Type的值为multipart/form-data,这是原来表单的encType属性值。并且要提交数据需要使用FormData对象来存储数据。

upload.js:处理上传文件。这里使用了app.get('/upload-file.html')渲染upload-file.html页面,所以需要访问http://127.0.0.1:8989/upload-file.html打开页面进行上传文件,而不是像前面表单可以直接打开html文件进行提交,如果是那样就会造成跨域的问题。

// 第一步,引入express
var express = require("express");
// 引入文件上传模块express-fileupload
var fileUpload = require('express-fileupload');

// 第二步,创建服务器应用程序
var app = express();
// 配置文件上传模块
app.use(fileUpload());

// 渲染upload-file.html文件
app.get('/upload-file.html', function (request, response) 
    require('fs').readFile('./upload-file.html', function (err, data) 
        response.end(data);
    );
);

app.post('/upload', function (request, response) 
    console.log(request.files);
    var avatarFile = request.files.avatar;// 注意avatar对应input标签的name属性值
    // 处理文件上传失败
    if (!request.files || Object.keys(request.files).length === 0) 
        return response.status(400).send("没有文件被上传!")
    
    // 获取上传文件名
    var fileName = avatarFile.name;
    // 设定文件的保存路径
    var uploadPath = __dirname + "/upload/img/" + fileName;
    // 使用mv方法来将上传文件保存到指定路径下
    avatarFile.mv(uploadPath, function (err) 
        if (err)
            return response.status(500).send(err);
        response.send('文件上传成功!');
    );
);

// 监听端口
app.listen(8989, function () 
    console.log("app is running at port 8989.");
);

Node.js---中间件

Node.js -- Express框架中间件

浅谈对express中间件的的理解。

Node.js 表达了对 bodyParser 中间件的正确使用

Node.js 表达了对 bodyParser 中间件的正确使用

Node.js Express框架 详细总结