機智使用elementUI調用一次接口同時上傳圖片和文件,同時須要攜帶其餘參數,實現調用後端接口

今天有一個坑,同時要上傳圖片和文件,並且圖片要展現縮略圖,文件要展現列表。
個人思路是:
首先,只上傳附件照片,這個直接看ele的官方例子就行,不只僅上傳附件照片,還同時上傳其餘參數。
而後,再作上傳照片和文件,上傳其餘參數,其實也就是文件合併。

1、上傳照片和其餘參數

頁面樣式大約就是這樣的,參數有優先級,發生時間,服務單名稱,服務單描述,圖片附件上傳。


(一)視圖部分代碼:
<el-form-item prop="image" label="圖片附件上傳">
          <el-upload
            ref="upload"
            :action="uploadAction"
            :beforeUpload="beforeUploadPicture"
            :on-change="imageChange"
            list-type="picture-card"
            name="files"
            :data="paramsData"
            :limit="3"
            multiple
            :auto-upload="false"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemovePicture">
            <i class="el-icon-plus"></i>
          </el-upload>
          <el-dialog :visible.sync="dialogVisible">
            <img width="100%" :src="dialogImageUrl" alt="">
          </el-dialog>
     </el-form-item>

 <el-button size="mini" type="primary" @click="confirm()">確 定</el-button>複製代碼
說明:
一、action變量爲後端圖片接口的地址
二、beforeUpload方法是指的上傳以前觸發的函數,能夠用來作前端文件格式判斷,文件大小判斷
三、on-change方法是指每次選擇文件都會觸發函數,能夠用來前端刪除和添加照片
四、list-type屬性指的是照片picture-card展現的方式
五、name指的是上傳的文件字段名,這是後端確認文件流的字段名,能夠隨便寫
六、data屬性指的是上傳時附帶的額外參數,這是指的其餘參數
七、limit屬性指的是上傳文件的個數極限。
八、multiple屬性指的是能夠每次多選文件,true爲多選,false爲單選
九、auto-upload屬性指的是自動上傳的,true爲能夠自動上傳,false爲不能夠自動上傳
十、on-preview方法指的是查看縮略圖的方法
十一、on-remove方法指的是刪除文件的方法
十二、ref綁定dom元素

(二)data部分代碼
data () {
    return {
      selectedCategorySpe: this.selectedCategory,
      serviceForm: {
        title: '',
        desc: '',
        priority: '',
        occurDate: ''
      },
       dialogImageUrl: '',
       dialogVisible: false,
      uploadAction: "/inner/event/order/submit/submit" + "&accessToken=" + this.$store.getters.token
    }
  },複製代碼


(三)computed部分代碼
computed: {
    ...mapGetters([
      'constConfig'
    ]),
    paramsData: function () {
      let params = {
        eventCategory: this.selectedCategorySpe.categoryId,
          priority: this.serviceForm.priority,
          title: this.serviceForm.title,
          dsc: this.serviceForm.desc,
          occurDate: this.serviceForm.occurDate
      }
      return params
    }
  },複製代碼
使用computed實現實時監測paramsData的值,只要selectedCategorySpe.categoryId,serviceForm.priority,serviceForm.title
,serviceForm.desc,serviceForm.occurDate中只有一個變化,都會從新計算paramsData的值。

(四)methods部分方法
beforeUploadPicture(file){
      const isImage = file.type == 'image/png' || file.type == 'image/jpg' ||  file.type == 'image/jpeg' || file.type == 'image/bmp' || file.type == 'image/gif' || file.type == 'image/webp';
      const isLt2M = file.size <  1024 * 1024 * 2;
      if (!isImage) {
        this.$message.error('上傳只能是png,jpg,jpeg,bmp,gif,webp格式!');
      }
      if (!isLt2M) {
        this.$message.error('上傳圖片大小不能超過 2MB!');
      }
      return isImage && isLt2M;
    },
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    handleRemovePicture(file, fileList) {
      console.log(file, fileList);
    },
    imageChange(file, fileList, name) {
      console.log(file, fileList);
    },

 confirm(){
    this.$refs.upload.submit();
    }複製代碼
說明:confirm使用ref的綁定的upload,緊接着調用form的表單的submit方法。這個vue已經封裝好了,這時候傳的參數能夠看到post傳遞的文件對象。




2、同時上傳圖片和文件,而且圖片能夠看縮略圖文件顯示成列表

可是當你出現這樣的需求的時候,一臉矇蔽


(一)視圖部分代碼
<el-form-item prop="image" label="圖片附件上傳">
          <el-upload
            ref="uploadImage"
            :action="uploadAction"
            :beforeUpload="beforeUploadPicture"
            :on-change="imageChange"
            list-type="picture-card"
            name="files"
            :limit="3"
            multiple
            :auto-upload="false"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemovePicture">
            <i class="el-icon-plus"></i>
          </el-upload>
          <el-dialog :visible.sync="dialogVisible">
            <img width="100%" :src="dialogImageUrl" alt="">
          </el-dialog>
        </el-form-item>
        <el-form-item prop="image" label="文件附件上傳">
          <el-upload
            ref="uploadFile"
            class="upload-demo"
            name="files"
            :on-change="fileChange"
            :action="uploadAction"
            :on-preview="handlePreviewFile"
            :on-remove="handleRemoveFile"
            :before-remove="beforeRemoveFile"
            multiple
            :auto-upload="false"
            :limit="3"
            :on-exceed="handleExceedFile"
            :file-list="fileList">
            <el-button size="small" type="primary">點擊上傳</el-button>
            <!--<div slot="tip" class="el-upload__tip">只能上傳文件,且不超過2M</div>-->
          </el-upload>
        </el-form-item>

 <el-button size="mini" type="primary" @click="confirm()">確 定</el-button>複製代碼

(2)data部分數據
data () {
    return { 
      selectedCategorySpe: this.selectedCategory,
      serviceForm: {
        title: '',
        desc: '',
        priority: '',
        occurDate: '',
      },
      images: {},
      files: {},
      dialogImageUrl: '',
      dialogVisible: false
    }
  },複製代碼

(3)method部分數據
beforeUploadPicture(file){
     const isImage = file.type == 'image/png' || file.type == 'image/jpg' ||  file.type == 'image/jpeg' || file.type == 'image/bmp' || file.type == 'image/gif' || file.type == 'image/webp';
      const isLt2M = file.size <  1024 * 1024 * 2;
      if (!isImage) {
        this.$message.error('上傳只能是png,jpg,jpeg,bmp,gif,webp格式!');
      }
      if (!isLt2M) {
        this.$message.error('上傳圖片大小不能超過 2MB!');
      }
      return isImage && isLt2M;
    },
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },
    handleRemovePicture(file, fileList) {
      console.log(file, fileList);
    },
    imageChange(file, fileList, name) {
      console.log(file, fileList);
      this.imageList = fileList;
      this.images['images'] = fileList;
    },

    handleRemoveFile(file, fileList) {
      console.log(file, fileList);
    },
    handlePreviewFile(file) {
      console.log(file);
    },
    handleExceedFile(files, fileList) {
      this.$message.warning(`當前限制選擇 3 個文件,本次選擇了 ${files.length} 個文件,共選擇了 ${files.length + fileList.length} 個文件`);
    },
    beforeRemoveFile(file, fileList) {
      return this.$confirm(`肯定移除 ${ file.name }?`);
    },
    fileChange(file,fileList) {
      console.log(file, fileList);
      this.fileList = fileList;
      this.files['files'] = fileList;
 },複製代碼
confirm(){
          let wfForm = new FormData();
          wfForm.append( 'eventCategory',this.selectedCategorySpe.categoryId)
          wfForm.append( 'priority',this.serviceForm.priority)
          wfForm.append( 'title',this.serviceForm.title)
          wfForm.append( 'dsc',this.serviceForm.desc)
          wfForm.append( 'occurDate',this.serviceForm.occurDate)
          Object.entries(this.images).forEach(file => {
            file[0].forEach(item => {
              // 下面的「images」,對應後端須要接收的name,這樣對圖片和文件作一個區分,name爲images爲圖片
              wfForm.append('images', item.raw)
              // wfForm.append(item.name, file[0])
            })
          })
          Object.entries(this.files).forEach(file => {
            file[0].forEach(item => {
              // 下面的「files」,對應後端須要接收的name,name爲files爲文件
              wfForm.append('files', item.raw)
              //wfForm.append(item.name, file[0])
            })
          })
          createEventOrder(wfForm).then( res => {
            console.log(res, 'res')
            if(res.retValue === 1){
              this.$message.success( '成功建立服務單' );
              this.handleClose()
            }else{

            }
          })

    }複製代碼
說明一下,新建了this.files存文件列表,this.images存圖片列表。在confirm中新建一個FormData對象,使用append方法將參數變量加到數據對象中,和文件對象。最後將FormData對象傳給後端。
傳遞的參數截圖以下:

這回對images和files,圖片和文件作區分,後端也須要作個判斷,其餘的參數不須要的參數能夠選擇不傳,須要增長新的參數,使用append的方法添加。


2019.07.11【說明】

根據評論中提到的問題
 this.files[''] = fileList;意義不大,這個就是想用一個對象存那個文件對象,對象須要一個name,本身取一個,也能夠爲空。改爲這樣也行: this.files['files'] = fileList;這樣作的目的是若是你的文件上傳和圖片上傳用一個this.fileImage對象的話,在最後包裝formData的時候能夠經過對象的name區分,哪一個是文件,哪一個是圖片,用一次 Object.entries(this.images).forEach 就能夠把formData包裝好,更符合前端的高複用,低代碼的思想。

我怕有人理解不了這個,我仍是補充一下代碼:前端

(2)data部分數據(新增一個fileImage)
vue

fileImage: {},複製代碼

(3)methods中修改這塊web

一、圖片上傳的這塊修改成後端

if(isImage && isLt2M){  
    this.imageList = fileList;  
    this.fileImage['images'] = fileList;}else{  
    fileList.splice(-1,1);
}複製代碼

二、文件上傳的這塊修改成
bash

if(!isImage && isLt2M){  
    this.fileList = fileList;  
    this.fileImage['files'] = fileList;}else{  
    fileList.splice(-1,1);
}複製代碼

三、提交那塊,把兩個forEach合併成一個,而後直接取對象的name最爲formData的name。app

Object.entries(this.fileImage).forEach(file => {      file[1].forEach(item => {    
        wfForm.append(file[0], item.raw)    
    })
})

複製代碼
最後也能夠看到,也是ok的複製代碼



【歡迎關注,有什麼問題,歡迎提出,我看到有空就回答】dom

相關文章
相關標籤/搜索