今天有一个坑,同时要上传图片和文件,并且图片要展现缩略图,文件要展现列表。前端
个人思路是:vue
首先,只上传附件照片,这个直接看ele的官方例子就行,不只仅上传附件照片,还同时上传其余参数。web
而后,再作上传照片和文件,上传其余参数,其实也就是文件合并。后端
页面样式大约就是这样的,参数有优先级,发生时间,服务单名称,服务单描述,图片附件上传。app
(一)视图部分代码:dom
<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变量为后端图片接口的地址post
二、beforeUpload方法是指的上传以前触发的函数,能够用来作前端文件格式判断,文件大小判断this
三、on-change方法是指每次选择文件都会触发函数,能够用来前端删除和添加照片url
四、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传递的文件对象。
可是当你出现这样的需求的时候,一脸蒙蔽
(一)视图部分代码
<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的方法添加。
根据评论中提到的问题
this.files[''] = fileList;
意义不大,这个就是想用一个对象存那个文件对象,对象须要一个name,本身取一个,也能够为空。改为这样也行:
this.files['files'] = fileList;
这样作的目的是若是你的文件上传和图片上传用一个this.fileImage对象的话,在最后包装formData的时候能够经过对象的name区分,哪一个是文件,哪一个是图片,用一次
Object.entries(this.images).forEach
就能够把formData包装好,更符合前端的高复用,低代码的思想。
我怕有人理解不了这个,我仍是补充一下代码:
(2)data部分数据(新增一个fileImage)
fileImage: {},
(3)methods中修改这块
一、图片上传的这块修改成
if(isImage && isLt2M){ this.imageList = fileList; this.fileImage['images'] = fileList;}else{ fileList.splice(-1,1); }
二、文件上传的这块修改成
if(!isImage && isLt2M){ this.fileList = fileList; this.fileImage['files'] = fileList;}else{ fileList.splice(-1,1); }
三、提交那块,把两个forEach合并成一个,而后直接取对象的name最为formData的name。
Object.entries(this.fileImage).forEach(file => { file[1].forEach(item => { wfForm.append(file[0], item.raw) }) })
最后也能够看到,也是ok的
【欢迎关注,有什么问题,欢迎提出,我看到有空就回答】