今天有一個坑,同時要上傳圖片和文件,而且圖片要展示縮略圖,文件要展示列表。
我的思路是:
首先,只上傳附件照片,這個直接看ele的官方例子就行,不僅僅上傳附件照片,還同時上傳其他參數。
然后,再做上傳照片和文件,上傳其他參數,其實也就是文件合並。
一、上傳照片和其他參數
頁面樣式大約就是這樣的,參數有優先級,發生時間,服務單名稱,服務單描述,圖片附件上傳。

(一)視圖部分代碼:
<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>
說明:
1、action變量為后端圖片接口的地址
2、beforeUpload方法是指的上傳之前觸發的函數,可以用來做前端文件格式判斷,文件大小判斷
3、on-change方法是指每次選擇文件都會觸發函數,可以用來前端刪除和添加照片
4、list-type屬性指的是照片picture-card展示的方式
5、name指的是上傳的文件字段名,這是后端確認文件流的字段名,可以隨便寫
6、data屬性指的是上傳時附帶的額外參數,這是指的其他參數
7、limit屬性指的是上傳文件的個數極限。
8、multiple屬性指的是可以每次多選文件,true為多選,false為單選
9、auto-upload屬性指的是自動上傳的,true為可以自動上傳,false為不可以自動上傳
10、on-preview方法指的是查看縮略圖的方法
11、on-remove方法指的是刪除文件的方法
12、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傳遞的文件對象。

二、同時上傳圖片和文件,並且圖片可以看縮略圖文件顯示成列表
但是當你出現這樣的需求的時候,一臉蒙蔽

(一)視圖部分代碼
<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)
fileImage: {},
(3)methods中修改這塊
1、圖片上傳的這塊修改為
if(isImage && isLt2M){
this.imageList = fileList;
this.fileImage['images'] = fileList;}else{
fileList.splice(-1,1);
}
2、文件上傳的這塊修改為
if(!isImage && isLt2M){
this.fileList = fileList;
this.fileImage['files'] = fileList;}else{
fileList.splice(-1,1);
}
3、提交那塊,把兩個forEach合並成一個,然后直接取對象的name最為formData的name。
Object.entries(this.fileImage).forEach(file => { file[1].forEach(item => {
wfForm.append(file[0], item.raw)
})
})
最后也可以看到,也是ok的

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