表单数据和文件上传四种思路:
1、文件和表单数据一起上传到后端,即后端一个接口接收文件和表单数据(这种是比较古老的方法,后端接口复杂度也大,且不易实现上传文件进度条等功能,不推荐)
2、先上传文件,然后后端保存文件(先不进行数据库写入),返回一个文件的url给前端,前端收到url后和其他表单数据一起提交给后端,后端再一起写入数据库(要求后端将上传文件的接口独立出来,推荐)
3、先上传文件,然后后端保存文件,并写入数据库,得到数据库id,将数据库id返回给前端,前端将表单数据和数据库id一起发送给后端,然后后端根据数据库id找到该记录,在更新表单数据到该记录
4、先上传表单数据,然后后端保存表单数据,写入数据库,然后前端在点击上传文件(并传递之前上传表单数据的数据库id),后端接收到文件保存后,将url更新进表单数据里(这种方法最容易实现,但是用户需要两次操作才能更新表单数据和文件,不像第二和第三种,只需要点击提交表单后就可以更新)
使用el-upload上传文件
使用el-upload还需要注意的是:
action属性发送的请求是使用内部封装的ajax请求,所以不会经过你自己封装的axios,所以如果你配置来代理,需要你自己为该请求添加代理前缀,如果使用了token身份校验,你还需要为本次请求添加请求头
el-upload的name属性的就是本次发送请求文件的参数名,需要将他更改为后端需要的参数名
接下来是使用上面说的第二种方法来进行表单数据和文件一起上传
html部分
<el-form :rules="categoryRules" ref="categoryRuleForm" :model="categoryForm">
<el-form-item label="分类名称" label-width="120px" prop="category_name">
<el-input v-model="categoryForm.category_name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="分类图片" label-width="120px" prop="category_pic">
<el-upload
list-type="picture-card"
:limit="1"
:on-exceed="handleExceed"
name="category_pic"
action="/api/category/uploadPic"
:headers="headerObj"
:on-remove="handleRemove"
:on-success="handleCategoryPicSuccess"
:file-list="fileList"
:before-upload="beforeCategoryPicUpload"
>
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{file}">
<img
class="el-upload-list__item-thumbnail"
:src="" alt=""
>
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in"></i>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleDownload(file)"
>
<i class="el-icon-download"></i>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete"></i>
</span>
</span>
</div>
</el-upload>
<el-dialog :="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</el-form-item>
</el-form>
js部分
<script>
import {getToken} from '@/utils/auth'
import { getCategoryList, addCategory, updateCategory, deleteCategory, deleteCategoryPic } from '../../api/category'
export default {
name: '',
data () {
return {
categoryForm: {
category_name: '', // 分类名称
category_pic: '', // 分类图片
},
// el-upload的请求头
headerObj: {
Authorization: `Bearer ${getToken()}`,
},
fileList: [], // 上传时的图片列表(这里的图片将会显示出缩略图)
// 大图预览相关
dialogImageUrl: '',
dialogVisible: false,
disabled: false
}
},
mounted () {
},
methods: {
// 添加分类
addCategory() {
this.addDialogFormVisible = false
let result = await addCategory({
category_name: this.categoryForm.category_name,
category_pic: this.categoryForm.category_pic,
})
if(result.code === 200){
this.$message.success(result.message)
this.getCategoryList()
}else{
this.$message.error(result.message)
}
},
// 上传图片成功
handleCategoryPicSuccess(res, file) {
// 将服务器返回的文件url地址赋值给表单的category_pic,这样就可以在表单提交时将图片地址提交到服务器
this.categoryForm.category_pic = res.data.category_pic
this.getCategoryList()
// 提示信息
this.$message({
message: '图片上传成功',
type: 'success'
});
},
// 上传图片前
beforeCategoryPicUpload(file) {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
const isLt1M = file.size / 1024 / 1024 < 1;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG / PNG 格式!');
}
if (!isLt1M) {
this.$message.error('上传头像图片大小不能超过 1MB!');
}
return isJPG && isLt1M;
},
// 图片超出限制
handleExceed(files, fileList) {
this.$message.error('当前限制选择 1 张图片!');
},
// 点击删除按钮
async handleRemove(file) { // 删除图片
// 删除缩略图图片
this.fileList.splice(this.fileList.indexOf(file), 1);
// 发送请求删除服务器图片
let result = await deleteCategoryPic({
category_pic: this.categoryForm.category_pic,
})
if(result.code === 200){
this.$message.success(result.message)
}else{
this.$message.error(result.message)
}
},
// 点击大图预览按钮
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
// 点击下载按钮
handleDownload(file) {
// 提示
this.$message({
message: '暂未开发',
type: 'danger'
});
}
}
}
</script>