vue |通過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'}})
  })
},


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM