博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于Vue + Node.js + MongoDB的图片上传组件,实现图片的预览和删除
阅读量:6470 次
发布时间:2019-06-23

本文共 8640 字,大约阅读时间需要 28 分钟。

公司要写一些为自身业务量身定制的的组件,要基于Vue,写完后扩展了一下功能,选择写图片上传是因为自己之前一直对这个功能比较迷糊,所以这次好好了解了一下。演示在网址打开后的show.gif中。

使用技术:Vue.js | node.js | express | MongoDB。

github网址:

图片描述

功能

  • 单图多图上传
  • 图片上传预览
  • 上传进度条
  • 分组上传,分组查询
  • 新建分组,删除分组
  • 删除图片
  • 选择图片

目录结构

clipboard.png

前端利用Vue搭建,Entry.vue中引入子组件Upload.vue。在Upload.vue中,使用input标签,上传图片,form表单提交数据,但是from让人很头疼,提交后刷新页面,所以给它绑定了一个隐藏的iframe标签来实现无刷新提交表单。

Dom中:

调用上传函数提交完数据后:

upload();document.forms[0].target="rfFrame";

图片预览

利用html5的fileReader对象

let count = 0;//上传函数外定义变量,记录文件的数量,即递归的次数/*-----------------------此段代码在上传函数中-------------------------------*/   let fileReader = new FileReader();   //解析图片路径,实现预览   fileReader.readAsDataURL(file.files[count]);   fileReader.onload=()=>{      previewData = {         url:fileReader.result,//图片预览的img标签的src         name:file.files[count].name,         size:file.files[count].size,      };      //这段代码在上传函数中,所以在外面定义了一个_this = this,fileList为vue的data中定义的状态    _this.fileList.push(previewData);   };

进度条实现

在axios的配置中定义onUploadProgress函数,接收参数:progressEvent,利用它的两个属性:progressEvent.total和progressEvent.loaded(上传的文件总字节数和已上传的字节数)
node写接口,实现图片的接收、查询、删除。实现分组的新增、查询、删除。利用Formidable模块接收并处理前端传过来的表单数据。利用fs模块实现删除文件功能。

let progress = 0;let config = {  headers: {'Content-Type': 'multipart/form-data'},  onUploadProgress (progressEvent){    if(progressEvent.lengthComputable){      progress = progressEvent.total/progressEvent.loaded;      _this.$refs.progress[_this.$refs.progress.length-1].style.width = Number(progress).toFixed(2)*100+"%";    }  }};

向formData中插入文件

formData = new FormData();if(file.files[count]){formData.append('file',file.files[count],file.files[count].name);

对于上传方式,我这里统一采用依次上传,无论是单图多图,单图上传一次就好,多图则递归调用上传函数,直到递归次数等于图片数量,停止递归。

上传函数

let file=$event.target,      formData = new FormData();      //递归调用自身,实现多文件依次上传      let _this = this;      let count = 0;      let previewData = {};    uploadImage($event){      let file=$event.target,      formData = new FormData();      //递归调用自身,实现多文件依次上传      let _this = this;      let count = 0;      let previewData = {};      function upload(){        //开始上传时,滚到底部        _this.$refs.picWrapper.scrollTop = _this.$refs.picWrapper.scrollHeight;        //定义axios配置信息        let progress = 0;        let config = {          headers: {'Content-Type': 'multipart/form-data'},          onUploadProgress (progressEvent){            console.log(`进度条的数量${_this.$refs.progress.length -1}`);            if(progressEvent.lengthComputable){              progress = progressEvent.total/progressEvent.loaded;              //进度条              _this.$refs.progress[_this.$refs.progress.length-1].style.width = Number(progress).toFixed(2)*100+"%";            }          }        };        //向formData中插入文件        if(file.files[count]){        formData.append('file',file.files[count],file.files[count].name);        let fileReader = new FileReader();        //解析图片路径,实现预览        fileReader.readAsDataURL(file.files[count]);        fileReader.onload=()=>{          previewData = {            url:fileReader.result,            name:file.files[count].name,            size:file.files[count].size,          };          _this.fileList.push(previewData);          _this.progressShow = true        };        fileReader.onloadend=()=>{          //检测图片大小是否超出限制          if(formData.get('file').size>_this.maxSize){            formData.delete('file');            //当图片全部上传完毕,停止递归            count++;            if(count > file.files.length-1){              return            }            upload()          }else{              //发送数据              axios.post(`/upload?mark=${_this.group}`,formData,config).then((response)=>{                formData.delete('file');                let res = response.data;                console.log(res);                if(res.result){                  //如果是新建上传                  if(_this.group === 'new'){                    _this.fileList.push(res.data);                      _this.fileList.forEach((item,index)=>{                          if(!item.newName){                            _this.fileList.splice(index,1)                          }                      })                    }else{                    //如果是选择其他组上传,直接把返回数据赋值到文件数组                      _this.fileList = res.data;                    }                  _this.newUpload = false                }else{                  alert('上传失败');                  return;                }                _this.noPic = false;                count++;                if(count > file.files.length-1){                  return                }                upload()              }).catch((err)=>{                alert('上传失败123');              });            }        };        }      }      //第一次调用      upload();      document.forms[0].target="rfFrame";

}

node.js写后端

//引入表单处理模块let Formidable = require("formidable");

一系列定义....

form.encoding = 'utf-8';form.uploadDir = '/project/vue/vue_uploader/my-server/public/images';//定义文件存放地址form.keepExtensions = true;form.multiples = false;//以单文件依次上传的方式,实现多文件上传form.maxFieldsSize = 1*1024;//解析图片,重命名图片名称,返回给前端。let fileData = "";let fileDir = "images";//定义文件的存放路径let route = 'upload_';//定义路由let serverIp = 'http://localhost:3002/';//定义服务器IP

对文件数据进行处理,存入本地并存入数据库(由于涉及到分组上传。。。所以比较复杂)

解析文件函数:

function handleFile (file){    let filename = file.name;    let nameArray = filename.split('.');    let type = nameArray[nameArray.length-1];    let name = '';    for (let i = 0;i
{ if(err){ res.json({ result:false, msg:err.message }) }else{ if(doc){ doc.picList.push(fileData); doc.save((err,saveResult)=>{ if(err){ return res.json({ result:false, }); }else{ let length= doc.picList.length; console.log(doc.picList.length) if(groupMark === 'all'){ UploadData.find({},(err,queryResult)=>{ if(err){ res.json({ result:false, mgs:'发生错误了' }) }else{ let allPic = []; queryResult.forEach((item)=>{ if(item.group !=='default'){ allPic = allPic.concat(item.picList) } }); res.json({ result:true, data:allPic.concat(queryResult[1].picList) }) } }) }else if(groupMark === 'new'){ UploadData.findOne({group:'default'},(err,queryResult)=>{ if(err){ return res.json({ result:false, msg:err.message }); }else{ return res.json({ result:true, data:queryResult.picList[queryResult.picList.length-1] }) } }); }else{ UploadData.findOne({group:group},(err,queryResult)=>{ if(err){ return res.json({ result:false, msg:err.message }); }else{ return res.json({ result:true, data:queryResult.picList }) } }); } } }) } } })}

最后,调用解析文件函数

form.parse(req,(err,fields,files)=>{    //传多个文件    if(files.file instanceof Array){        return    }else{     //传单个文件        handleFile(files.file)    }});

数据库结构:

clipboard.png

剩下的还有文件删除,新增分组,删除分组,分组查询的功能,由于篇幅有限,这些功能可以去

第一次用node和mongoDB写后台业务,还有很多地方需要完善,代码会继续更新~

转载地址:http://dwjko.baihongyu.com/

你可能感兴趣的文章
在一个form中有两个submit,值分别为修改和删除,如何在提交时用js判断submit值为修改还是删除呢...
查看>>
flash重点积累
查看>>
寻找第k元
查看>>
PHP极速开发框架LotusAdmin page版发布
查看>>
display属性
查看>>
REVEAL APP for IOS 永久试用
查看>>
雷林鹏分享:PHP 变量
查看>>
实现用户要求的若干道2年级四则运算题程序测试
查看>>
dataList中实现用复选框一次删除多行问题
查看>>
Java中throws和throw的区别讲解
查看>>
Spring(四)注解配置Ioc
查看>>
FreeCodeCamp:Confirm the Ending
查看>>
把媒体当手段还是当目的?
查看>>
pycharm 常用设置
查看>>
Win8 XAML 自定义控件资源加载与释放窍门
查看>>
hdu2149
查看>>
你真的会使用XMLHttpRequest吗?
查看>>
二分图匹配的两个主要算法 模板
查看>>
Windows XP系统上安装CitrixReceiver 3.2启用本地输入法localime报错
查看>>
Linux(CentOS)安装Oracle_11g_r2数据库(二)安装
查看>>