基于Vue + Node.js + MongoDB的图片上传组件,实现图片的预览和删除

释放双眼,带上耳机,听听看~!

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

使用技术:Vue.js | node.js | express | MongoDB。 
github网址:https://github.com/capslocktao/private-project/tree/master/vue_uploader

基于Vue + Node.js + MongoDB的图片上传组件,实现图片的预览和删除

功能

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

目录结构

基于Vue + Node.js + MongoDB的图片上传组件,实现图片的预览和删除

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

Dom中:


1
2
3
4
5
6
1<form class="upload-content-right-top" enctype="multipart/form-data" ref="formSubmit" >
2    <label class="upload-content-right-top-btn">上传图片</label>
3    <input type="file" @change="uploadImage($event)" multiple="multiple" accept="image/gif, image/jpeg, image/png">
4</form>
5<iframe id="rfFrame" name="rfFrame" src="about:blank" style="display:none;"></iframe>
6

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


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

图片预览 
利用html5的fileReader对象


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

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


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

向formData中插入文件 
formData = new FormData(); 
if(file.files[count]){ 
formData.append(‘file’,file.files[count],file.files[count].name);

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

上传函数


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
1   let file=$event.target,
2      formData = new FormData();
3      //递归调用自身,实现多文件依次上传
4      let _this = this;
5      let count = 0;
6      let previewData = {};
7
8
9    uploadImage($event){
10      let file=$event.target,
11      formData = new FormData();
12      //递归调用自身,实现多文件依次上传
13      let _this = this;
14      let count = 0;
15      let previewData = {};
16
17      function upload(){
18        //开始上传时,滚到底部
19        _this.$refs.picWrapper.scrollTop = _this.$refs.picWrapper.scrollHeight;
20        //定义axios配置信息
21        let progress = 0;
22        let config = {
23          headers: {'Content-Type': 'multipart/form-data'},
24          onUploadProgress (progressEvent){
25            console.log(`进度条的数量${_this.$refs.progress.length -1}`);
26            if(progressEvent.lengthComputable){
27              progress = progressEvent.total/progressEvent.loaded;
28              //进度条
29              _this.$refs.progress[_this.$refs.progress.length-1].style.width = Number(progress).toFixed(2)*100+"%";
30            }
31          }
32        };
33        //向formData中插入文件
34        if(file.files[count]){
35        formData.append('file',file.files[count],file.files[count].name);
36        let fileReader = new FileReader();
37        //解析图片路径,实现预览
38        fileReader.readAsDataURL(file.files[count]);
39        fileReader.onload=()=>{
40          previewData = {
41            url:fileReader.result,
42            name:file.files[count].name,
43            size:file.files[count].size,
44          };
45          _this.fileList.push(previewData);
46          _this.progressShow = true
47        };
48        fileReader.onloadend=()=>{
49          //检测图片大小是否超出限制
50          if(formData.get('file').size>_this.maxSize){
51            formData.delete('file');
52            //当图片全部上传完毕,停止递归
53            count++;
54            if(count > file.files.length-1){
55              return
56            }
57            upload()
58          }else{
59              //发送数据
60              axios.post(`/upload?mark=${_this.group}`,formData,config).then((response)=>{
61                formData.delete('file');
62                let res = response.data;
63                console.log(res);
64                if(res.result){
65                  //如果是新建上传
66                  if(_this.group === 'new'){
67                    _this.fileList.push(res.data);
68                      _this.fileList.forEach((item,index)=>{
69                          if(!item.newName){
70                            _this.fileList.splice(index,1)
71                          }
72                      })
73
74                    }else{
75                    //如果是选择其他组上传,直接把返回数据赋值到文件数组
76                      _this.fileList = res.data;
77                    }
78
79                  _this.newUpload = false
80                }else{
81                  alert('上传失败');
82                  return;
83                }
84                _this.noPic = false;
85                count++;
86                if(count > file.files.length-1){
87                  return
88                }
89                upload()
90              }).catch((err)=>{
91                alert('上传失败123');
92              });
93            }
94        };
95        }
96      }
97      //第一次调用
98      upload();
99      document.forms[0].target="rfFrame";
100

node.js后端实现


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1一系列定义….
2form.encoding = ‘utf-8’;
3form.uploadDir = ‘/project/vue/vue_uploader/my-server/public/images’;//定义文件存放地址
4form.keepExtensions = true;
5form.multiples = false;//以单文件依次上传的方式,实现多文件上传
6form.maxFieldsSize = 1*1024;
7//解析图片,重命名图片名称,返回给前端。
8let fileData = “”;
9let fileDir = “images”;//定义文件的存放路径
10let route = ‘upload_’;//定义路由
11let serverIp = ‘http://localhost:3002/‘;//定义服务器IP
12
13对文件数据进行处理,存入本地并存入数据库(由于涉及到分组上传。。。所以比较复杂)
14
15解析文件函数:
16function handleFile (file){
17let filename = file.name;
18let nameArray = filename.split(‘.’);
19let type = nameArray[nameArray.length-1];
20let name = ”;
21for (let i = 0;i< nameArray.length - 1;i++){
22name = name + nameArray[i];
23}
24let date = new Date();
25let time = ‘’ + date.getFullYear() + “” + date.getMonth() + “” + date.getDay() + “” + date.getHours() + “” + date.getMinutes() +”“+ date.getSeconds()+”_”+date.getMilliseconds();
26let picName = name + time + ‘.’ + type;
27let newPath = form.uploadDir + “/” + picName;
28let oldPath = form.uploadDir + “/”+ file.path.substring(file.path.indexOf(route));
29

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
1  fs.renameSync(oldPath, newPath); //重命名
2    fileData = {
3        id:`${new Date().getTime()}`,
4        url:serverIp + newPath.substring(newPath.indexOf(fileDir)),
5        name:file.name,
6        size:file.size,
7        isSelected:false,
8        newName:picName,
9    };
10    UploadData.findOne({group:group},(err,doc)=>{
11        if(err){
12            res.json({
13                result:false,
14                msg:err.message
15            })
16        }else{
17            if(doc){
18                doc.picList.push(fileData);
19                doc.save((err,saveResult)=>{
20
21                    if(err){
22                        return res.json({
23                            result:false,
24                        });
25                    }else{
26                        let length= doc.picList.length;
27                        console.log(doc.picList.length)
28                        if(groupMark === 'all'){
29                            UploadData.find({},(err,queryResult)=>{
30                                if(err){
31                                    res.json({
32                                        result:false,
33                                        mgs:'发生错误了'
34                                    })
35                                }else{
36                                    let allPic = [];
37                                    queryResult.forEach((item)=>{
38                                        if(item.group !=='default'){
39                                            allPic = allPic.concat(item.picList)
40                                        }
41                                    });
42                                        res.json({
43                                            result:true,
44                                            data:allPic.concat(queryResult[1].picList)
45                                        })
46
47                                }
48                            })
49                        }else if(groupMark === 'new'){
50
51                            UploadData.findOne({group:'default'},(err,queryResult)=>{
52                                if(err){
53                                    return res.json({
54                                        result:false,
55                                        msg:err.message
56                                    });
57                                }else{
58                                    return res.json({
59                                        result:true,
60                                        data:queryResult.picList[queryResult.picList.length-1]
61                                    })
62                                }
63                            });
64
65                        }else{
66                            UploadData.findOne({group:group},(err,queryResult)=>{
67                                if(err){
68                                    return res.json({
69                                        result:false,
70                                        msg:err.message
71                                    });
72                                }else{
73                                    return res.json({
74                                        result:true,
75                                        data:queryResult.picList
76                                    })
77                                }
78                            });
79                        }
80                    }
81                })
82
83            }
84
85        }
86
87    })
88}
89

最后,调用解析文件函数 


1
2
3
4
5
6
7
8
9
10
1form.parse(req,(err,fields,files)=>{
2//传多个文件
3if(files.file instanceof Array){
4return
5}else{
6//传单个文件
7handleFile(files.file)
8}
9});
10

数据库结构:

基于Vue + Node.js + MongoDB的图片上传组件,实现图片的预览和删除

 

转载于:https://www.cnblogs.com/catbrother/p/9397573.html

给TA打赏
共{{data.count}}人
人已打赏
安全技术

【JWT】JWT+HA256加密 Token验证

2021-8-18 16:36:11

安全技术

C++ 高性能服务器网络框架设计细节

2022-1-11 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索