vue+node实现图片上传+预览

先上效果图 在这里插入图片描述

上代码

html部分主要是借助了weui的样式

<template>
  <div>
    <myheader :title="'发布动态'">
      <i class="iconfont icon-fanhui1 left" slot="left" @click="goback"></i>
    </myheader>
    <div class="upload">
      <div v-if="userInfo._id">
        <!--图片上传-->
        <div class="weui-gallery" id="gallery">
          <span class="weui-gallery__img" id="galleryImg"></span>
          <div class="weui-gallery__opr">
            <a href="javascript:" class="weui-gallery__del">
              <i class="weui-icon-delete weui-icon_gallery-delete"></i>
            </a>
          </div>
        </div>
        <div class="weui-cells weui-cells_form">
          <div class="weui-cell">
            <div class="weui-cell__bd">
              <textarea class="weui-textarea" v-model="content" placeholder="你想说啥" rows="3"></textarea>
            </div>
          </div>
          <div class="weui-cell">
            <div class="weui-cell__bd">
              <div class="weui-uploader">
                <div class="weui-uploader__bd">
                  <ul class="weui-uploader__files" id="uploaderFiles">
                    <li ref="files" class="weui-uploader__file" v-for="(image,index) in images" :key="index"
                        :style="'backgroundImage:url(' + image +' )'"><span @click="deleteimg(index)" class="x">&times;</span></li>
                  </ul>
                  <div v-show="images.length < maxCount" class="weui-uploader__input-box">
                    <input @change="change" id="uploaderInput" class="weui-uploader__input " type="file"
                          multiple accept="image/*">
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <a class="weui-btn weui-btn_primary btn-put" style="margin: 20px " @click.prevent.once="put">发送</a>
      </div>
      <unlogin v-else> </unlogin>
    </div>
  </div>
</template>

重点部分在于

<ul class="weui-uploader__files" id="uploaderFiles">
  <li ref="files" class="weui-uploader__file" v-for="(image,index) in images" :key="index"
      :style="'backgroundImage:url(' + image +' )'"><span @click="deleteimg(index)" class="x">&times;</span></li>
</ul>
<div v-show="!this.$refs.files||this.$refs.files.length < maxCount" class="weui-uploader__input-box">
  <input @change="change" id="uploaderInput" class="weui-uploader__input" type="file"
         multiple accept="image/*">
</div>

通过@change="change"监听图片的上传,把图片转成base64后(后面会讲怎么转base64)将base64的地址加入到images数组,通过v-for="(image,index) in images"把要上传的图片在页面中显示出来,即达到了预览的效果

js部分
data部分

data() {
      return {
        content: '',//分享动态的文字内容
        maxSize: 10240000 / 2,//图片的最大大小
        maxCount: 8,//最大数量
        filesArr: [],//保存要上传图片的数组
        images: []//转成base64后的图片的数组
      }
    }

delete方法

deleteimg(index) {
        this.filesArr.splice(index, 1);
        this.images.splice(index, 1);
      }

change方法

change(e) {
        let files = e.target.files;
        // 如果没有选中文件,直接返回
        if (files.length === 0) {
          return;
        }
        if (this.images.length + files.length > this.maxCount) {
          Toast('最多只能上传' + this.maxCount + '张图片!');
          return;
        }
        let reader;
        let file;
        let images = this.images;
        for (let i = 0; i < files.length; i++) {
          file = files[i];
          this.filesArr.push(file);
          reader = new FileReader();
          if (file.size > self.maxSize) {
            Toast('图片太大,不允许上传!');
            continue;
          }
          reader.onload = (e) => {
            let img = new Image();
            img.onload = function () {
              let canvas = document.createElement('canvas');
              let ctx = canvas.getContext('2d');
              let w = img.width;
              let h = img.height;
              // 设置 canvas 的宽度和高度
              canvas.width = w;
              canvas.height = h;
              ctx.drawImage(img, 0, 0, w, h);
              let base64 = canvas.toDataURL('image/png');
              images.push(base64);
            };
            img.src = e.target.result;
          };
          reader.readAsDataURL(file);
        }
      }

put方法把filesArr中保存的图片通过axios发送到后端,注意要设置headers信息

put() {
        Indicator.open('发布中...');
        let self = this;
        let content = this.content;
        let param = new FormData();
        param.append('content', content);
        param.append('username', this.userInfo._id);
        this.filesArr.forEach((file) => {
          param.append('file2', file);
        });
        self.axios.post('/upload/uploadFile', param, {
          headers: {
            "Content-Type": "application/x-www-form-urlencoded"
          }
        }).then(function (result) {
          console.log(result.data);
          self.$router.push({path: '/home'});
          Indicator.close();
          Toast(result.data.msg)
        })
      }

后端通过multer模块保存传输的图片,再把保存下来的图片发送到阿里云oss(这个可以根据自己的使用情况变化)

let filePath;
let fileName;

let Storage = multer.diskStorage({
    destination: function (req, file, cb) {//计算图片存放地址
        cb(null, './public/img');
    },
    filename: function (req, file, cb) {//图片文件名
        fileName = Date.now() + '_' + parseInt(Math.random() * 1000000) + '.png';
        filePath = './public/img/' + fileName;
        cb(null, fileName)
    }
});
let upload = multer({storage: Storage}).any();//file2表示图片上传文件的key

router.post('/uploadFile', function (req, res, next) {
    upload(req, res, function (err) {
        let content = req.body.content || '';
        let username = req.body.username;
        let imgs = [];//要保存到数据库的图片地址数组
        if (err) {
            return res.end(err);
        }
        if (req.files.length === 0) {
            new Pyq({
                writer: username,
                content: content
            }).save().then((result) => {
                res.json({
                    result: result,
                    code: '0',
                    msg: '上传成功'
                });
            })
        }
        /*client.delete('public/img/1.png', function (err) {
            console.log(err)
        });*/
        let i = 0;
        req.files.forEach((item, index) => {
            let filePath = `./public/img/${item.filename}`;
            put(item.filename,filePath,(result)=>{
                imgs.push(result.url);
                i++;
                if (i === req.files.length) {
                //forEach循环是同步的,但上传图片是异步的,所以用一个i去标记图片是否全部上传成功
                //这时才把数据保存到数据库
                    new Pyq({
                        content: content,
                        writer: username,
                        pimg: imgs
                    }).save().then(() => {
                        res.json({
                            code: '0',
                            msg: '发布成功'
                        });
                    })
                }
            })
        })
    })
});

如果你对这个项目有兴趣,你可以去看看我的另一篇文章VueSocial(仿微博、微信的聊天社交平台)

完整在线demo地址 VueSocial(移动端最好使用浏览器打开,pc端按了f12后有个小问题,刷新一下就好,resize触发的问题,待改进)

github地址
如果觉得这篇文章对你有帮助或者觉得这个项目还不错,请留下你的star,谢谢。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在Vue中使用Element UI上传图片预览可以按照以下步骤进行: 1. 首先,在项目中安装Element UI和axios: ``` npm install element-ui axios --save ``` 2. 在main.js中引入Element UI和axios,并使用: ```javascript import Vue from 'vue' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' import axios from 'axios' Vue.use(ElementUI) Vue.prototype.$axios = axios ``` 3. 在组件中使用`<el-upload>`组件进行文件上传,并使用`<el-image>`组件进行预览: ```html <template> <div> <el-upload action="/api/upload" :on-success="handleSuccess" :on-preview="handlePreview" list-type="picture-card"> <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="dialogVisible"> <el-image :src="imageUrl" :preview-src-list="previewImages"></el-image> </el-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false, imageUrl: '', previewImages: [] }; }, methods: { handleSuccess(response) { if (response.status === 200) { this.imageUrl = response.data.url; this.previewImages.push(response.data.url); } }, handlePreview(file) { this.dialogVisible = true; this.imageUrl = file.url; this.previewImages = [file.url]; } } } </script> ``` 4. 在服务器端设置相应的文件上传接口,例如使用Node.js和express: ```javascript const express = require('express'); const multer = require('multer'); const app = express(); const upload = multer({ dest: 'uploads/' }); app.post('/api/upload', upload.single('file'), (req, res) => { // 处理上传文件并返回文件URL const file = req.file; const url = `http://example.com/${file.filename}`; res.send({ url }); }); app.listen(3000, () => { console.log('Server is running on port 3000'); }); ``` 上述代码实现了一个简单的上传图片预览的功能,具体可根据实际需求进行调整和扩展。 ### 回答2: 在Vue中使用Element UI上传图片预览可以按照以下步骤进行: 1. 首先,在项目中引入Element UI组件库,并在需要使用的组件中进行注册。 ```js import Vue from 'vue' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) ``` 2. 创建一个上传组件,并初始化需要的数据,如图片列表和上传接口等。 ```vue <template> <div> <el-upload action="/your-upload-url" :on-success="handleSuccess" :file-list="fileList" :on-remove="handleRemove" multiple > <el-button size="small" type="primary"> 选择图片 </el-button> </el-upload> <el-image v-for="(file, index) in fileList" :key="index" :src="file.url" :preview-src-list="previewList" fit="cover" style="width: 100px; height: 100px;" ></el-image> </div> </template> <script> export default { data() { return { fileList: [], // 上传的文件列表 previewList: [] // 预览图片列表 } }, methods: { handleSuccess(response, file, fileList) { // 上传成功的回调函数 fileList[fileList.length - 1].url = URL.createObjectURL(file.raw) this.previewList = fileList.map(file => file.url) }, handleRemove(file, fileList) { // 上传文件移除的回调函数 this.previewList = fileList.map(file => file.url) } } } </script> ``` 在上述代码中,el-upload组件负责上传图片,action属性指定上传图片的接口地址,on-success属性可以监听上传成功的事件,并通过handleSuccess方法返回上传成功后的处理方式。file-list属性用于展示上传成功的文件列表,并且绑定了on-remove属性来处理上传文件的移除事件。 el-image组件用于展示预览图片,v-for指令遍历渲染fileList数组中的每张图片,通过src属性绑定图片的地址,在handleSuccess方法中将上传成功的文件通过URL.createObjectURL方法生成临时的URL作为图片的地址。同时,preview-src-list属性绑定了previewList数组,用于展示预览图片的列表。 这样,当用户选择图片上传成功后,页面将会展示上传图片,并提供预览功能。 ### 回答3: 使用Element UI库实现图片上传预览的步骤如下: 1. 首先,在项目中引入Element UI和Vue插件。 ``` import Vue from 'vue'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); ``` 2. 在Vue组件中,添加一个上传组件和一个用于预览图片的容器。 ``` <template> <div> <!-- 图片上传组件 --> <el-upload class="upload-demo" action="/your-upload-api" <!-- 上传图片的接口地址 --> :on-success="handleUploadSuccess" > <el-button size="small" type="primary">点击上传</el-button> </el-upload> <!-- 图片预览容器 --> <div class="preview-container"> <img :src="imageUrl" v-if="imageUrl" alt="预览图片" /> </div> </div> </template> <script> export default { data() { return { imageUrl: '' // 预览图片的URL }; }, methods: { handleUploadSuccess(response) { // 上传成功后,将返回的图片URL赋值给imageUrl this.imageUrl = response.data.imageUrl; } } }; </script> ``` 3. 完成上述代码后,当用户选择图片上传成功时,上传接口会返回图片的URL。通过`handleUploadSuccess`方法将返回的URL赋值给`imageUrl`,然后在预览容器中显示预览图片即可。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值