我是想要实现表单加上图片的上传
首先前端代码
<template>
<div>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" enctype='multipart/form-data'>
<el-form-item label="分类" prop="study_type">
<el-radio-group v-model="ruleForm.type">
<el-radio-button label="轻量级框架"></el-radio-button>
<el-radio-button label="主流前端框架"></el-radio-button>
<el-radio-button label="工具"></el-radio-button>
<el-radio-button label="CSS生态"></el-radio-button>
<el-radio-button label="JS生态"></el-radio-button>
<el-radio-button label="VUE生态"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item label="链接" prop="link">
<el-input v-model="ruleForm.link"></el-input>
</el-form-item>
<el-form-item label="简介" prop="info">
<el-input type="textarea" v-model="ruleForm.info" :autosize="{ minRows: 4, maxRows: 6}"></el-input>
</el-form-item>
<el-form-item>
<el-upload
ref="upload"
action=""
:auto-upload="false"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-success="uploadSuccess">
<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>
<el-button type="primary" @click="submitForm('ruleForm')">保存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props:[''],
data () {
return {
ruleForm: {
type: '轻量级框架',
name: '',
link: '',
info: '',
},
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ min: 1, max: 15, message: '长度在 1 到 15 个字符', trigger: 'blur' }
],
link: [
{ required: true, message: '请输入链接', trigger: 'blur' },
{ min: 1, max: 255, message: '长度在 1 到 255 个字符', trigger: 'blur' }
],
info: [
{ required: true, message: '请填写简介', trigger: 'blur' }
]
},
dialogImageUrl: '',
dialogVisible: false,
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
//用formdata传递数据
const formData = new FormData();
//上传图片
const file = this.$refs.upload.uploadFiles[0]
formData.append('file', file.raw);
formData.append('name', this.ruleForm.name);
formData.append('type', this.ruleForm.type);
formData.append('info', this.ruleForm.info);
formData.append('link', this.ruleForm.link);
this.$http.post('/study/add',formData).then(res => {
console.log(res.data)
})
} else {
console.log('error submit!!');
return false;
}
});
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
uploadSuccess(response, file){
console.log(response)
console.log(file)
},
}
</script>
前端页面
后台很重要
- 1.首先要获取静态资源,这样就可以通过http://localhost:3000/XXXX.jpg拿到图片
//app.js
const static = require('koa-static')//获取静态资源
app.use(static(
path.join(__dirname, './upload')//获取static文件夹下的资源,url不加static http://localhost:3000/avatar.png
))
- 2.需要安装koa-multer,可以单独写个文件导出,我是写在一个文件里,然后写接口
//study.js
const multer = require('koa-multer')//解析上传文件
const path = require('path')
let storage = multer.diskStorage({
//定义文件保存路径
destination: path.resolve('upload'),//路径根据具体而定。如果不存在的话会自动创建一个路径
filename: (ctx, file, cb)=>{
cb(null, file.originalname);
},
//修改文件名
filename:function(req,file,cb){
var fileFormat = (file.originalname).split(".");
cb(null,Date.now() + "." + fileFormat[fileFormat.length - 1]);
}
});
let upload = multer({ storage: storage});
router.post('/add',passport.authenticate('jwt', { session: false }),upload.single('file'), async ctx => {
console.log(ctx.req.body)//获取上传的表单数据
console.log(ctx.req.file)//获取上传的文件图片数据
})
实例
-
前台post请求
-
获取到的图片
-
后台获取到的数据
-
加上数据库
遇到的问题
- 如果用elementUI的action属性,将文件用this.$refs.upload.submit()上传,就会发送2次post请求,就会导致提交表单一次,上传图片一次,在后台就会取不到表单数据或者图片数据,所以我采用了formData传递数据的方式。
- 我在测试接口的时候一直都没有给返回值,所以一直报404,记得给返回值。
- 第一次用formData传递数据,还不是很清楚,我在测试的时候,ctx.request是空的,但是ctx.req却有数据,查找资料。
(1)ctx.request:是Koa2中context经过封装的请求对象,它用起来更直观和简单。
(2)ctx.req:是context提供的node.js原生HTTP请求对象。这个虽然不那么直观,但是可以得到更多的内容,适合我们深度编程。