• vuejs| 通过promise实现图片批量上传


    需求

    • 批量上传头像,且头像能上传到对应的人员信息上
    • 上传限制
    • 不是立刻上传

    修改默认样式

    因为觉得element组件的el-upload有点复杂,所以这里使用原始的input标签。不过通常需要换掉原始样式,只需给input添加一条style="display:none",接着用具有其他样式的元素包裹它,并在该元素上添加事件(不包裹也行,包裹主要是为了容易看)。

    <el-button  @click="beforeImagesUpload">批量上传图片
        <input type="file" style="display:none" id="file" multiple>
    </el-button>
    

    点击触发该事件相当于点击了里面的input元素

    beforeImagesUpload(){
        let file = document.querySelector('#file')//获取最原始的input元素
        file.click()//触发
    }
    

    保存图片信息

    现在要在上面的beforeImagesUpload进行丰富。由于我希望头像能上传到对应的人员信息上,那么我至少需要有一个标识帮助我识别这个头像属于谁。所以上传前先要求用户将图片命名为对应的id,接着前端通过图片名称来获取对应的标识进行文件上传。

    这里先了解一下图片文件的数据格式:

    image.png

    如果不想立刻上传,那么很容易想到的办法就是先将文件储存起来:

    fileList:[]
    
    async beforeImagesUpload(){
        let fileList=[]
        let file = document.querySelector('#file')
        file.click()
        file.onchange = function (event) {
          let files = event.target.files
          for(let i=0;i<files.length;i++){
                let file=files[i]
                let filename=file.name//获取图片名称(有后缀)
                let id=filename.slice(0,filename.indexOf('.'))//获取图片名称(无后缀)
                fileList.push({file:file,id:id,filename:filename})//整合成新的图片对象,并将其加进图片列表中
            }
    	}
        console.log(fileList)//出错
    }
    

    然而,你会发现控制台打印数据是空的。这是由于同步致使函数直接跳过处理图片的部分,马上到了后面的console.log(fileList)

    Promise实现异步

    这时可以使用promise对象解决。promise对象的函数内有两个参数:resolve和reject,它们是两个回调函数,前者表示成功时的回调,后者表示失败时的回调,这里先不考虑reject的情况:

    async beforeImagesUpload(){
      let that=this//改变作用域
      let promise= new Promise(function (resolve, reject) {
          let fileList=[]
          let file = document.querySelector('#file')
          file.click()
          file.onchange = function (event) {
            let files = event.target.files
          	for(let i=0;i<files.length;i++){
                let file=files[i]
                let filename=file.name
                let id=filename.slice(0,filename.indexOf('.'))
                fileList.push({file:file,id:id,filename:filename})
            }
            resolve(fileList)//通过resolve将fileList抛出,在后续使用
        }
      })
      
      //接着就是处理抛出来的数据了:
      //promise接受两个回调函数作为参数:一个状态变为Resolved时调用,一个是状态变为Reject时调用。
      //这两个函数都接受Promise对象传出的值作为参数。
      //第二个函数是可选的,这里先不考虑第二个函数。
      promise.then(function(value) {
        //状态为resolved时调用,这里的value就是resolve抛出的数据
        console.log(value)//成功打印
        that.fileList=value//储存
      });
      
    },
    

    为了更好的处理数据,建议把value传给另一个函数处理:

    promise.then(function(value) {
        	that.upload(value)//正式上传 后面写
    	}
    )
    

    添加限制

    假设上传图片有两个前提:

    1.最多只能上传10张

    2.图片大小不能大于300k

    这里reject就派上用场的了。现在修改一下promise对象中的内容:

    //...
    let promise= new Promise(function (resolve, reject) {
        //...
        file.onchange = function (event) {
          let files = event.target.files
          
          //1.判断图片数量
          if(files.length>10){
            reject('page')//如果多于10张,判定为失败,抛出错误'page',停止向下运行。
          }else{
            for(let i=0;i<files.length;i++){
              let file=files[i]
              
              //2.判断图片大小
              const is300K=file.size>300*1024//判定指标,是否大于300k
              if (is300K) {
                reject('size')//如果大于300k,判定为失败,抛出错误'size',停止向下运行。
              }
              
              let fileName=file.name
              let phone=fileName.slice(0,fileName.indexOf('.'))
              fileList.push({file:file,phone:phone,fileName:fileName})
            }
          }
          resolve(fileList)//上面均没有出错时抛出
      }
    })
    

    接下来就是处理回调函数:

    async beforeImagesUpload(){
      //...
      let promise= new Promise(function (resolve, reject) {
          //...
      })
      
      
      //这里需要promise的第二个回调函数,在状态为Reject时调用:
      promise.then(function(value) {
        that.upload(value)//正式上传
      }, function(error) {
        //上面设置了两种错误,这里可以用if来判断错误类型,并给出对应的响应
        if(error=='page'){
          that.$message.error('最多只能上传10张照片!')
        }else if(error=='size'){
          that.$message.error('上传的图片大小不能超过300K!');
        }
      });
        
      
    },
    

    图片上传

    不是立刻上传,需要将upload(value)传过来的值先保存起来,如this.fileList=value,再经过中间函数处理,配合弹框使用。

    为了简便,这里就直接上传了。批量上传,说白了其实就是一个一个地上传,这里我使用的是axios插件:

    upload(value){
      value.map(item=>{
        let fd = new FormData()
        fd.append('image',item.file)
        fd.append('id',item.id)
        axios.post("url",fd,{headers:{'Content-Type': 'multipart/form-data'}})
      })
    },
    
  • 相关阅读:
    使用Hibernate需要导入的一些JAR包
    Eclipse+MyEclipse+Tomcat的配置
    ant安装、环境变量配置及验证
    怎样关闭占用80端口的pid为4的进程
    查看80端口是否被占用
    python爬虫-抓取acg12动漫壁纸排行设置为桌面壁纸
    WPF--鼠标右键菜单中的Command命令实现
    WPF-TreeView获取文件夹目录、DataGrid获取目录下文件信息
    IOS学习[Swift中跳转与传值]
    IOS学习【xcode 7新特性url链接】
  • 原文地址:https://www.cnblogs.com/sanhuamao/p/14068101.html
Copyright © 2020-2023  润新知