NodeJS + Express + busboy 实现图片上传接口并回显

1,186 阅读2分钟

大家好 我是前端小白 多的不说 少的不唠 先上效果图

如果只需要代码 请前往目录三

20220815_214920.gif

前言

在准备之前 可以先简单了解以下busboy是干什么的 有什么作用

busboy:个节点,js模块,用于解析传入的HTML表单数据。

了解之后 再依次安装以下依赖

  • npm i express
  • npm i busboy
  • npm i cors

一、开始搭建服务器

  • 在目录中创建一个app.js文件 并复制以下代码
const express = require('express');

const app = express();

// 解决跨域问题
app.use(cors())

app.get('/', (req, res) => {
    res.send('<h1>Hello World!</h1>');
})

// 开启服务器 监听3000端口
app.listen(3000,()=>{
    console.log('服务器启动中 地址:http://localhost:3000');
})
  • 创建完后 执行 node app.js 命令 即可启动服务器

1.png

  • 此时浏览器输入 http://localhost:3000 即可看到hello word

2.png

  • 现在开始书写post接口

1 - 引入busboy依赖

在app.js中添加

const Busboy = require('busboy')

2 - 引入path、fs模块

在app.js中添加

const path = require('path')
const fs = require('fs')

3 - 书写post接口

在app.js中添加

app.post('/uploads',function(req,res){
    const bb = Busboy({ headers: req.headers });

    let data = {
        filename:'', // 图片名字
        encoding:'', // 图片大小
        mimeType:'', // 图片格式
        imgUrl:'' // 图片地址
    }

    bb.on('file', (name, file, info) => {
        // 名字 大小 格式
        const { filename, encoding, mimeType } = info;
        // 根据时间创建名字 - 防止重名
        const filePath = new Date().getTime() + path.extname(filename)
        // 保存数据
        data = {...info,filename:filePath}
        // 拼接地址
        const saveTo = path.join(__dirname, './uploads', filePath);
        // 写入流
        file.pipe(fs.createWriteStream(saveTo));
    }); 

    bb.on('finish', function () {
        // 地址回显
        data.imgUrl = 'http://127.0.0.1:3000/uploads/' + data.filename
        // 返回图片
        res.send({
            code:200,
            msg:'上传成功',
            data
        });
    });
    
    return req.pipe(bb);
});

注意 需要先在目录中创建一个uploads文件夹 否则会报错

4.png

4 - 托管文件夹

在app.js中添加

// 托管静态文件
app.use('/uploads',express.static(__dirname+'/uploads')) // 图片文件夹路径

5 - 使用postman测试一下接口是否正常

3.png 测试正常 复制这个url地址 浏览器打开查看是否能够看到图片

5.png 图片显示也正常 开始书写表单

二、书写表单 发送请求

新建index.html文件 复制以下代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="file">
    <button>上传</button>
    <br>
    <img id="img">
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.js"></script>
    <script>
        let file = document.querySelector('input[type="file"]');
        let button = document.querySelector('button');
        let img = document.getElementById('img');
        button.addEventListener('click', function () {
            var formData = new FormData();
            formData.append('file', file.files[0]);
            axios.post('http://localhost:3000/uploads', formData).then(function (res) {
                img.src = res.data.data.imgUrl
            }).catch(function (err) {
                console.log(err);
            });
        });
    </script>
</body>
</html>

测试

20220815_214920.gif

三、全部代码

app.js

const express = require('express');
const Busboy = require('busboy')
const path = require('path')
const fs = require('fs')
const cors = require('cors')
const app = express();

// 解决跨域问题
app.use(cors())

app.get('/', (req, res) => {
    res.send('<h1>Hello World!</h1>');
})

// 托管静态文件
app.use('/uploads',express.static(__dirname+'/uploads')) // 图片文件夹路径

app.post('/uploads',function(req,res){
    const bb = Busboy({ headers: req.headers });

    let data = {
        filename:'', // 图片名字
        encoding:'', // 图片大小
        mimeType:'', // 图片格式
        imgUrl:'' // 图片地址
    }

    bb.on('file', (name, file, info) => {
        // 名字 大小 格式
        const { filename, encoding, mimeType } = info;
        // 根据时间创建名字 - 防止重名
        const filePath = new Date().getTime() + path.extname(filename)
        // 保存数据
        data = {...info,filename:filePath}
        // 拼接地址
        const saveTo = path.join(__dirname, './uploads', filePath);
        // 写入流
        file.pipe(fs.createWriteStream(saveTo));
    }); 

    bb.on('finish', function () {
        // 地址回显
        data.imgUrl = 'http://127.0.0.1:3000/uploads/' + data.filename
        // 返回图片
        res.send({
            code:200,
            msg:'上传成功',
            data
        });
    });
    
    return req.pipe(bb);
});

// 开启服务器 监听3000端口
app.listen(3000,()=>{
    console.log('服务器启动中 地址:http://localhost:3000');
})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="file">
    <button>上传</button>
    <br>
    <img id="img">
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.js"></script>
    <script>
        let file = document.querySelector('input[type="file"]');
        let button = document.querySelector('button');
        let img = document.getElementById('img');
        button.addEventListener('click', function () {
            var formData = new FormData();
            formData.append('file', file.files[0]);
            axios.post('http://localhost:3000/uploads', formData).then(function (res) {
                img.src = res.data.data.imgUrl
            }).catch(function (err) {
                console.log(err);
            });
        });
    </script>
</body>
</html>

github地址:github.com/2289816251/…

6.png