vue+NodeJS+mysql数据库如何实现类似于b站发动态那样的多图上传功能(最详细教程)

740 阅读5分钟

我也是在自己做项目的时候想要模仿b站去实现类似于发动态的多图上传功能,遇到了许多困难,终于在最后是解决了,希望大家能够耐心看完,我们先来看一下演示效果。

QQ截图20221226165025.png 点击输入框输入配文,点击图片按钮选择想要发布的图片(上限9张)

QQ截图20221226165055.png 点击发布按钮之后成功在展示页面展示

大概的功能就是这样 这里我们着重讲解多图上传部分的实现

首先你要先获取input中你选中的图片文件,然后将其存储在一个数组当中, 下图通过ref获取图片文件(pic_data为你写的input输入框)他的files[0]即为你选择的图片文件, 随后将此文件保存在数组pic_list中

 // 这里的fileobj是一个blob格式的图片文件
        const fileObj = this.$refs.pic_data.files[0];
        this.pic_list.push(fileObj);

QQ截图20221226170203.png

之后点击发送按钮触发发送回调,将信息传到后端。这里我们需要创建一个formdata类型的对象,调用其append方法将数组中的文件加入formdata流中(这里append的第一个参数'file'只是一个名字,后端要用同样的名字去接收参数)。随后调用的自己定义的后端接口,传入formdata即可

async publish() {
      let formdata = new FormData();
      if (this.pic_list.length) {
        this.pic_list.forEach((item) => {
          formdata.append("file", item);
        });
      }
       let result = await this.$API.sendMessageInfo(formdata);       
    },

现在数据已成功传入后端,让我们看看后端要怎么接收我们发送的图片数据吧

这里小编使用的是express框架,首先是定义后端路由,这里我们需要用到connect-multiparty库,直接npm i connect-multiparty下载即可,随后如下图所示,在路由中使用创造出来的multipartMiddleware中间件,不然路由处理函数当中是收不到你传来的formdata数据的。

var multipart = require('connect-multiparty')
var multipartMiddleware = multipart();
// 动态发送图片
router.post('/sendPic', multipartMiddleware, userhandle.sendPic)

随后我在userhandle文件夹中定义路由处理函数sendPic。我们需要理解,当你将formdata点击发送给后端的那一刻,其实后端服务器就已经自动下载好了我们所传的图片,保存的位置的绝对路径在图片文件的path属性当中,我们之所以还要使用fs将其再复制到我们想要的文件夹下,只是为了方便管理

exports.sendMessage = (req, res) => {
//img_list存储每个图片的文件名 随后存入数据库中
    let img_list = []
    // 如果传了图片 就写入图片 这里files.file的file就是上面你append时的第一个参数
    if (req.files.file) {
    //这里的data就是你传来的图片文件数组
        const data = req.files.file
    //item是你传入的每个图片对象 其身上有一些我们需要的属性即下面item的属性
        data.forEach(item => {
        //使用fs将图片写入服务器你指定的目录下 第一个参数是指定的目录位置
        //第二个参数是写入图片的文件名,第三个参数是你要写入的图片在服务器的哪个路径下
             fs.writeFileSync('./static/' + item.originalFilename, fs.readFileSync(item.path));
                img_list.push(item.originalFilename)
            })
        } 
        //将图片名通过,连接成一个字符串 随后将此字符串存入数据库的message_img字段中 因为数据库存不了数组
        //至于怎么存入mysql数据库 学过nodejs应该都没有问题
        const img_str = img_list.join(',')
        //以下为你自己操作数据库的代码.....
}

下图为我数据库的截图

QQ截图20221226173920.png

此时static目录下也会有图片文件,我这里直接使用了图片文件本来的文件名,所以看着很乱,但是其实并不会出现问题,因为我们将图片名存在数据库每条动态信息的一个字段中,要展示图片的时候我们只需要将img标签的src属性改为数据库中的图片名称即可

QQ截图20221226172557.png

在app.js中设置static目录为静态资源目录

app.use(express.static('static'))

之后在前端我们只需要将img的src属性设置为 服务器域名+文件名即可展示图片(因为上面设置了static为静态资源目录) 下图的item是数据库中的每条动态,它的message_img字段即为我们上面拼在一起的图片名字符串, 我们把它用split还原回数组遍历,url就是每个图片的名字

 <img
     v-for="(url, index) in item.message_img.split(',')"
     :key="index"
     :src="'http://127.0.0.1:3008/' + url"
/>

到此,我们的页面上就会成功的渲染出我们发送的图片啦。

总结,如果是但图片上传,那会容易很多,直接将图片转为base64字符串以json格式传给后端即可;而多图上传,base64串会过长导致很明显的卡顿,所以我们需要借助formdata流将多张图片以formdata流的形式传输;后端则需要用相应的中间件进行解析之后能够在req.files中找到前端传入的图片(当然这里使用的是express框架,如果是koa框架,是支持formdata数据的,接收会方便很多)koa框架接收图片的学习视频我放在这里www.bilibili.com/video/BV13A… 收到传入的文件后,后端需要把文件的名字存储在数据库中,前端向后端发起请求获取数据库中的图片名称数据,再在页面上进行展示即可。

前端源码数据:mondy294/upload-many-pictures: 自己的网页终于实现多图上传 (github.com)

第一次写文章,我知道可能讲的还是有些粗糙,因为一些细枝末节的小地方我默认大家都已经会了,本文主要是为了告诉大家前端应该以何种形式向后端传递图片数据,以及后端该如何接收并统一存储这些图片,知道了这些其他有应该都不是问题,如果大家有什么问题可以私信我,感谢观看!!!。