上传图片并进行图片的预览效果(基于两种实现:vue和小程序)

因为实际的需求,使用vue的input组件,设置type=“file”,进行实现文件上传,并进行图片的预览,点击图片可进行删除操作
因为input组件原本的自身样式并没有办法与我设计图温和,所以在进行对input组件的宽高等处理后,通过定位的方式,将input组件至于最上层,并且设置opacity:0;达成最终的ui效果(具体的实现效果如下图)

在这里插入图片描述
(vue)页面布局

    <div class='apply-reason'>
      <div class='reason-box'>
        <div class='apply-reason-title'>问题描述</div>
        <div class='right'>
          <img :src='ossAddr("/img/mine/camera.png")'>
          <span>添加图片</span>
          <input class="img-upload" @change='chooseImg'  type="file">
        </div>
      </div>
      <div class='textarea-box'>
        <textarea v-model='content' maxlength='500' placeholder-class='textarea--placehoder' placeholder='请填写具体内容,帮助我们了解你的建议。'></textarea>
      </div>
      <template v-if="imgList.length!=0">
        <div class='show-img flex'>
          <div v-for="(item, index) in imgList" :key="index">
            <div class='img'>
              <span @click='deleteImage(index)' v-if="showDelete">X</span>
              <img :src='item' @click='showDeleteBtn'>
            </div>
          </div>
        </div>
      </template>
    </div>

(vue)页面样式

  /* 申诉理由 */
  .apply-reason{
    /* height: 346px; */
    padding: 26px 30px 0;
    background: #fff;
    margin-bottom: 20px;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
  }
  .apply-reason-2{
    height: 194px;
    padding-bottom: 0;
  }
  .apply-reason-title{
    font-size: 30px;/*px*/
    color: #17181A;
    /* padding-bottom: 27px; */
  }
  .textarea-box{
    flex: 1;
    position: relative;
    padding-top: 30px;
  }
  .apply-reason>input{
    min-height: 96px;
    font-size: 28px;/*px*/
    border: none;
    outline: none;
    flex: 1;
  }
  .textarea-box textarea{
    height: 180px;
    width: 100%;
    font-size: 32px;/*px*/
    color: #1A1717;
    outline: none;
    border: none;
    line-height: 44px;
  }
  /* textarea  placeholder样式*/
   input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{
    font-size: 28px;/*px*/
    color: #BDC1C7;
  }
   input:-moz-placeholder,textarea:-moz-placeholder{
    font-size: 28px;/*px*/
    color: #BDC1C7;
  }
   input::-moz-placeholder,textarea::-moz-placeholder{
    font-size: 28px;/*px*/
    color: #BDC1C7;
  }
   input:-ms-input-placeholder,textarea:-ms-input-placeholder{
    font-size: 28px;/*px*/
    color: #BDC1C7;
  }

  .textarea-box span{
    position: absolute;
    bottom: 0;
    right: 0;
    font-size: 24px;/*px*/
    color: #BDC1C7;
  }

  /* 图片上传 */
  .right,
  .reason-box{
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 28px;
    border-bottom: 2px solid rgba(0, 0, 0, 0.08);
  }
  .right{
    width: 168px;
    border: none;
    padding: 0;
    position: relative;
  }

  .right img{
    width: 38px;
    margin-right: 10px;
    max-height: 28px;
  }
  .right span{
    font-size: 28px;/*px*/
    color: #797C80;
  }
  .img-upload{
    width: 100%;
    height: 100%;
    background: #fff;
    position: absolute;
    top: 0;
    left: 0;
    opacity: 0;
    z-index: 19;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  /* 展示图片 */
  .show-img{
    justify-content: flex-start;
    display: flex;
    align-items: center;
    height: 130px;
    width: 100%;
    border-top: 1px solid #eee;
    padding: 20px 0;
  }
  .show-img .img{
    width: 100px;
    height: 100px;
    border: 1px dotted #ddd;
    border-radius: 10px;
    margin-right: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  .show-img .img img{
    max-width: 100%;
    max-height: 100%;
  }
  .show-img .img span{
    position: absolute;
    top: -10px;
    right: -10px;
    z-index: 3;
    width: 30px;
    height: 30px;
    text-align: center;
    line-height: 30px;
    border-radius: 50%;
    background-color: red;
    color: #fff;
    font-size: 20px;/*px*/
    overflow: hidden;
  }

主要的业务逻辑代码

  data () {
    return {
      imgList:[],
      imgData: {
          accept: 'image/gif, image/jpeg, image/png, image/jpg',
      },
      bean: {
        type: '需求',
        content: '',
        contacts:'',//联系方式
      },
      content: '',
      showDelete:false,
    }
  },
  methods:{
    // 点击删除图片
    deleteImage(data){
        const me = this;
        me.imgList.splice(data,1),//传入图片的index,单击哪张,边删除哪张
    },
    // 点击显示删除符号
    showDeleteBtn(){
      this.showDelete = true;//初始showDelete 为false,点击时进行展示
    },
    chooseType(type){
      this.bean.type = type
    },
    // 选择上传图片
    chooseImg(event){
      let me = this;
      if (me.imgList.length<3){
          me.uploadImg(event,(data)=>{
              me.imgList.push(data);
          })
      } else {//可进行最多可上传3张图片的提示
          return
      }
    },
    //实现上传的真正函数
    uploadImg(event,callBack){
        let me = this;
        let reader = new FileReader();
        if(event.target.files[0]&&event.target.files[0]!=''){
          var img1 = event.target.files[0];
        }
        let type = img1.type;
        let size = img1.size;
        if(me.imgData.accept.indexOf(type) == -1 || size>3145728){
          // 提示选择符合规定的图片格式   
          return false;
        }
        // if(size>3145728){
        //   // 提示选择符合规定的图片格式     
        //   return false;
        // }
        var uri = '';
        let form = new FormData();
        form.append('file',img1,img1.name)
        this.$axios.post('/api/user/file/uploadImage.json',form,{
          headers:{'Content-Type':'multipart/form-data'}
        }).then(response=>{
          uri = response.data.data.fullPath
          reader.readAsDataURL(img1);
          reader.onloadend=function(){
              if(callBack){
                callBack(uri)
              }
          }
        }) 
    },
    // 提交
    submit(){
      let me = this;
      me.contentFun();
      api.userFeedbackUrl(me.bean).then(response => {
          me.common.axiosSuccessFun({
            this: me,
            callBack(res){
              // 提交成功会有一个弹窗提示,点击确定回到首页            
            }
          }, response.data)
        }).catch((res)=>{
          me.common.axiosFailFun({
            this: me
        }, res)
      }) 
    },
    // 处理图片路径的函数,通常在将内容上传给后台的时候,会进行一些内容的处理
    contentFun(){
      let str = '';
      let imgList = this.imgList;
      imgList.forEach(function (val) {
        str += '<img src="' + val + '"/>';
      })
      let content = this.content + str;
      this.bean.content = content;
    },
  }

基于微信小程序的上传图片实现预览,长按显示删除按钮,进行图片的删除,ui实现与上图一致
页面搭建,bindlongtap:长按触发

<view class='apply-reason'>
  <view class='reason-box'>
    <view class='apply-reason-title'>问题描述</view>  
    <view class='right' bindtap='chooseImg'>
    <!-- mode='widthFix'  -->
      <image mode='aspectFill' src=''></image>
      <text>添加图片</text>
  </view>
  </view>
  <view class='textarea-box'>
    <textarea bindinput='getContent' maxlength='500' placeholder-class='textarea--placehoder' placeholder='请填写具体内容,帮助我们了解你的建议。'></textarea>
  </view>
  <block wx:if="{{imgList.length!=0}}">
    <view class='show-image flex'>
      <block wx:for="{{imgList}}" wx:key="{{index}}">
        <view class='image'>
          <text bindtap='deleteImage' data-index='{{index}}' wx:if="{{showDelete}}">X</text>
          <image mode='aspectFit' src='{{item}}' bindlongtap='showDeleteBtn'></image>
        </view>
      </block>
    </view>
  </block>
</view>

页面样式实现

/* 申诉理由 */
.apply-reason{
  width: 100%;
  /* height: 346rpx; */
  padding: 27rpx 30rpx 14rpx;
  background: #fff;
  margin-bottom: 20rpx;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}
.apply-reason-title{
  font-size: 30rpx;
  color: #17181A;
  /* padding-bottom: 27rpx; */
}
.textarea-box{
  flex: 1;
  position: relative;  
  padding-top: 30rpx;
}
.apply-reason input{
  min-height: 96rpx;
  font-size: 28rpx;
  flex: 1;
}
.textarea-box textarea{
  height: 180rpx;
  width: 100%;
  font-size: 32rpx;
  color: #1A1717;
  line-height: 44rpx;
}
.textarea--placehoder{
  font-size: 28rpx;
  color: #BDC1C7;
}
.textarea-box text{
  position: absolute;
  bottom: 0;
  right: 0;
  font-size: 24rpx;
  color: #BDC1C7;
}

/* 图片上传 */
.right,
.reason-box{
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 28rpx;
  border-bottom: 2rpx solid rgba(0, 0, 0, 0.08);     
}
.right{
  border: none;
  padding: 0;
}

.right image{
  width: 38rpx;
  margin-right: 10rpx;
  max-height: 28rpx;
}
.right text{
  font-size: 28rpx;
  color: #797C80;
}

/* 展示图片 */
.show-image{
  justify-content: flex-start;  
  display: flex;
  align-items: center;
  height: 130rpx;
  width: 100%;
  border-top: 1px solid #eee;
  padding: 20rpx 0;
}
.show-image .image{
  width: 100rpx;
  height: 100rpx;
  border: 1px dotted #ddd;
  border-radius: 10rpx;
  margin-right: 20rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.show-image .image image{
  max-width: 100%;
  max-height: 100%;
}
.show-image .image text{
  position: absolute;
  top: -10rpx;
  right: -10rpx;
  z-index: 3;
  width: 30rpx;
  height: 30rpx;
  text-align: center;
  line-height: 30rpx;
  border-radius: 50%;
  background-color: red;
  color: #fff;
  font-size: 20rpx;
  overflow: hidden;
}

业务逻辑代码

import api from '../../../../config/api.js';
const app = getApp();

Page({
  data: {
    imgList:[],
    bean: {
      type: '需求',
      content: ''
    },
    content: ''
  },
  chooseType(e) {
    let me = this;
    me.setData({
      'bean.type': e.currentTarget.dataset.type
    })
  },
  //获取input输入框中的内容
  inputTap(e) {
    let me = this;
    me.setData({
      ['bean.' + e.currentTarget.dataset.name]: e.detail.value
    })
  },
  提交内容
  submit(){
    let me = this;
    me.content();
	//进行内容提交的请求
      }
    })
  },
  getContent(e){
    this.setData({
      content: e.detail.value
    })
  },
  content(){
    let str = '';
    let imgList = this.data.imgList;
    imgList.forEach(function (val) {
		str+=`<img src="${val}">`
    })

    let content = this.data.content + str;
    this.setData({
      'bean.content': content
    })
  },
  chooseImg(){
    let me = this;
    if (me.data.imgList.length<3){
      me.upLoadImg((data) => {
        var imgList = me.data.imgList;
        imgList.push(data);
        me.setData({
          imgList: imgList
        })
      });
    } else {
     //提示最多可上传3张图片
    }
    
  },
  // 删除图片
  deleteImage: function (e) {
    let imgIndex = e.currentTarget.dataset.index;
    let imgList = this.data.imgList;
    imgList.splice(imgIndex, 1);
    this.setData({
      imgList: imgList
    })
  },
  // 长按图片显示删除符号
  showDeleteBtn: function () {
    this.setData({
      showDelete: true
    })
  }, 
   //上传图片,第一步选择图片
  upLoadImg(callBack){
    var me = this;
    wx.showActionSheet({
      itemList: ["从相册中选择", "拍照"],
      itemColor: "#333",
      success: function (res) {
        if (!res.cancel) {
          wx.chooseImage({
            count: 1,
            sourceType: res.tapIndex == 0 ? ["album"] : ["camera"],
            success: function (res) {
              me.uploadImgStep2(res.tempFilePaths[0], callBack);
            }
          })
        }
      }
    })
  },  
  //图片上传第二步
  uploadImgStep2(imgPath, callBack) {
    let me = this;
    var cookie = '';
    var index = 0;
    var path = '';
    for (var key in this.getCookieSync('MAIN_SESSION')) {
      if (index > 0) {
        cookie += ';'
      }
      cookie += key + '=' + this.getCookieSync('MAIN_SESSION')[key]
      index = index + 1;
    }
    var Header = {
      'wx_small_program': 'wx_small_program',
      'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
      'Cookie': cookie
    }
    wx.uploadFile({
      url: api.upLoadImgUrl,
      filePath: imgPath,
      header: Header,
      name: 'file',
      formData: {
        file: imgPath
      },
      success: function (res) {
        if (res.statusCode != 200) {
          wx.showModal({
            title: '提示',
            content: '上传失败',
            showCancel: false
          })
          return;
        } else {
          if (callBack){
            callBack(JSON.parse(res.data).data.fullPath);//上传成功,将返回的数据通过JSON进行处理,然后取出路径,将最后的路径作为参数传入callBack,在callBack中可以用其他参数名进行取得路径
          }
        }
      },
      fail: function (e) {
        wx.showModal({
          title: '提示',
          content: '上传失败',
          showCancel: false
        })
      },
      complete: function () {
        wx.hideToast();  //隐藏Toast
      }
    })
  },
})
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于SSM和Vue实现图片上传预览的代码示例: 前端代码: ``` <template> <div> <input type="file" ref="fileInput" accept="image/*" @change="handleFileUpload"> <img v-if="imageUrl" :src="imageUrl" style="max-width: 100%;"> </div> </template> <script> export default { data() { return { imageUrl: '', file: null } }, methods: { handleFileUpload() { this.file = this.$refs.fileInput.files[0]; this.previewImage(this.file); this.uploadFile(this.file); }, previewImage(file) { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = e => { this.imageUrl = e.target.result; } }, async uploadFile(file) { const formData = new FormData(); formData.append('file', file); try { const response = await this.$axios.post('/upload', formData); console.log(response.data); } catch (error) { console.log(error); } } } } </script> ``` 后端代码: ``` @Controller public class UploadController { @PostMapping("/upload") @ResponseBody public String upload(@RequestParam("file") MultipartFile file) throws IOException { // 保存文件到服务器 File uploadFile = new File("/path/to/upload/" + file.getOriginalFilename()); file.transferTo(uploadFile); // 返回文件访问路径 return "http://your.domain.com/upload/" + file.getOriginalFilename(); } } ``` 其中,前端代码使用了Vue.js框架和axios库,后端使用了Spring MVC框架。在前端,我们使用`<input type="file">`元素来让用户选择上传图片文件,然后使用FileReader API来预览图片;在上传文件时,我们将文件封装为FormData对象,并使用axios库发送POST请求到后端的/upload接口;在后端,我们使用Spring MVC框架的@RequestParam注解来接收上传的文件,并将文件保存到服务器上,最后返回文件的访问路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值