enctype=“multipart/form-data”

uniapp微信小程序

1.原图

uniapp实现表单提交带图片上传 在做表单提交的时候,我们可能面临有图片上传,放在原生的html就好解决,form标签加上_ico


uniapp实现表单提交带图片上传 在做表单提交的时候,我们可能面临有图片上传,放在原生的html就好解决,form标签加上_上传_02


页面部分

<form :model="data" @submit="submit" @reset="">
<view class="top bgbai u-m-t-30" :class="{disabled: !isaction && data.renz.id}">
<view class="u-flex item">
<view class="left required">公司全称</view>
<input type="text" placeholder-class="line" v-model="data.renz.name" placeholder="请填写公司全称" />
</view>
<view class="u-flex item">
<view class="left required">纳税人识别号</view>
<input type="number" maxlength="20" placeholder-class="line" v-model="data.renz.ident" placeholder="请填写纳税人识别号" />
</view>
<view class="u-flex item">
<view class="left required">公司地址</view>
<input type="text" class="u-flex-1" v-model="data.renz.code1" placeholder-class="line" placeholder="请填写公司地址" />
</view>
<view class="u-flex item">
<view class="left required">公司电话</view>
<input type="text" placeholder-class="line" v-model="data.renz.phone" placeholder="请填写公司电话" />
</view>
<view class="u-flex item">
<view class="left required">开户行</view>
<input type="text" placeholder-class="line" v-model="data.renz.khyh" placeholder="请填写开户行" />
</view>
<view class="u-flex item">
<view class="left required">开户行账户</view>
<input type="text" placeholder-class="line" v-model="data.renz.khhuser" placeholder="请填写开户行账户" />
</view>
<view class="item permit u-flex-col">
<view class="left u-m-b-15 required">营业执照:</view>
<view>
<view class="yingyezhizhao" @click="zhizhaoFile">
<image :src="tempAvatar ? tempAvatar : Img" mode="aspectFit"></image>
<view class="mycolse" v-show="isdel" @click.stop="removeTemp">
<u-icon name="close-circle-fill" size="46" color="#000000"></u-icon>
</view>
</view>
</view>
</view>
<view class="filetip xsize">
只支持中国大陆工商局或市场监督管理局颁发的工商营业执照,且必须在有效期内, 请格式要求:原件照片,扫描件或者加盖公章的复印件,支持.jpg.jpeg.gif.png 格式照片大小不超过2M上传最新的营业执照。
</view>
<view class="u-flex-col item permit">
<view class="left u-m-b-15">经营范围:</view>
<textarea
class="fwtextarea"
v-model="data.renz.fanwei"
placeholder="一般经营范围"
placeholder-class="line"
maxlength="200"
/>
</view>
<view class="checkAddress between u-font-28 u-m-t-30" @click="setmrAddress">
<text class="checkTxt">是否与默认收货地址一致</text>
<text class="goTo">点击前往>></text>
</view>
<view class="bgbai drawer" :class="{disabled: !isaction && data.renz.id}">
<view class="u-flex item">
<view class="left required">收票人姓名</view>
<input type="text" placeholder-class="line" v-model="data.userc.shname" placeholder="请填写收票人姓名" />
</view>
<view class="u-flex item">
<view class="left required">收票人手机</view>
<input type="text" placeholder-class="line" v-model="data.userc.tel" placeholder="请填写收票人手机" />
</view>
<view class="u-flex item" @tap="showgcsPicker">
<view class="left required">收票人省份</view>
<input type="text" placeholder-class="line" v-model="data.userc.provice" disabled class="u-flex-1" placeholder="选择省/市/区" />
<text class="mix-icon icon-you"></text>
</view>
<view class="u-flex item">
<view class="left required">详细地址</view>
<input type="text" placeholder-class="line" v-model="data.userc.address" placeholder="街道、楼牌号等" />
</view>
<view class="btn-wrap center u-flex-col u-m-t-50" v-show="!data.renz.id || isaction">
<u-button class="btn center" :custom-style="btnSytle" hover-class="none" shape="circle" @click="submit">提交</u-button>
</view>
</view>
</form>

js部分

<script>
import {checkStr, checkAddressCode, orgcodevalidate} from '@/common/js/util'
export default {
data(){
return {
data: {
renz: {
name: '',
ident: '',
code1: '',
phone: '',
khyh: '',
khhuser: '',
fanwei: ''
},
userc: {
shname: '',
tel: '',
provice: '',
address: ''
}
},
show: false,
imgaction: 'index.php?m=Wxapi&c=User&a=engineer',
CDN: this.CDN,
stateArr:['审核中','审核完成','工程商认证审核未通过'],
colorArr:['#ff0000','#08bb71','#999999'],
isaction: false,
isdel: false,
btnSytle: {
width: '100%',
height: '80rpx',
fontSize: '32rpx',
borderRadius: '40rpx',
color: '#fff',
backgroundColor: 'transparent',
backgroundImage: 'linear-gradient(to left, rgb(250, 176, 34) ,#f83600)'
},
tempAvatar: '',
Img: '/static/icon/cream.png',
filesize: 0,
isModel: false //是否显示模态框
}
},
methods: {
// 上传营业执照
zhizhaoFile(){
let that = this;
uni.chooseImage({
count: 1,
sizeType: 'original', //指定原图
success: res=> {
that.filesize = res.tempFiles[0].size/1024/1024; //转换MB
if(that.filesize > 1){
that.$util.msg('上传文件大小不能超过1MB');
return;
}
that.tempAvatar = res.tempFilePaths[0];
},
error: err=>{
console.log(err)
}
})
},
// 提交认证
submit(){
const userid = uni.getStorageSync('uniIdToken') || 0;
if(userid <= 0){
this.$util.msg('请先登录!');
return;
}
const datas = this.data.renz;
const userdata = this.data.userc;
if(!datas.name){
this.$util.msg('请输入公司全称');
return;
}
if(datas.ident){
if(!checkStr(datas.ident, 'zzsnsno')){
this.$util.msg('纳税人识别号位数限制为15、18、20位,请检查');
return;
}else{
let addressCode = datas.ident.substring(0,6);
let ischeck = checkAddressCode(addressCode);
if(!ischeck){
this.$util.msg('请输入正确的纳税人识别号 (地址码)');
return;
}else{
// 校验组织机构代码
let orgCode = datas.ident.substring(6, 9);
let istrue = orgcodevalidate(orgCode);
if(!istrue){
this.$util.msg('请输入正确的纳税人识别号 (组织机构代码)');
return;
}
}
}
}else{
this.$util.msg('请输入纳税人识别号');
return;
}
if(!datas.code1){
this.$util.msg('请输入公司地址');
return;
}
if(!datas.phone){
this.$util.msg('请输入公司电话');
return;
}
if(datas.khyh){
if(!checkStr(datas.khyh, 'chinese')){
this.$util.msg('开户行须为中文');
return;
}
}else{
this.$util.msg('请输入开户行');
return;
}
if(datas.khhuser){
if(!checkStr(datas.khhuser, 'number')){
this.$util.msg('开户行账户格式错误');
return;
}
}else{
this.$util.msg('请输入开户行账户');
return;
}
if(this.tempAvatar){
if(this.filesize > 1){
this.$util.msg('上传文件大小不能超过1MB');
return;
}
}else{
this.$util.msg('请上传营业执照');
return;
}
if(!userdata.shname){
this.$util.msg('请输入收票人姓名');
return;
}
if(userdata.tel){
if(!checkStr(userdata.tel, 'mobile')){
this.$util.msg('手机号码格式错误');
return;
}
}else{
this.$util.msg('请输入收票人手机号码');
return;
}
if(!userdata.provice){
this.$util.msg('请选择地区');
return;
}
if(!userdata.address){
this.$util.msg('请输入详细地址');
return;
}
var obj = Object.assign(datas,userdata);
obj = JSON.parse(JSON.stringify(obj));
obj.uid = userid;
// obj.shname = userdata.name;
uni.showLoading({
title: '提交中...',
mask: true
})
if(this.tempAvatar === this.CDN + this.data.renz.pic1){
// 旧图片未修改
this.oldUpload(obj);
}else{
// 重新上传图片
this.yesUpload(obj);
}
},
// 旧图片未改调用
async oldUpload(data){
const res = await this.$request.post(this.imgaction,data);
if(res.status === 200){
uni.hideLoading();
this.$util.msg(res.msg);
this.isaction = this.isdel = false;
if(res.data.renz){
this.data.renz = res.data.renz;
this.data.renz.khyh = res.hang;
this.data.renz.khhuser = res.hangzh;
}
if(res.data.userc){
this.data.userc = res.data.userc;
this.data.userc.shname = res.data.userc.name;
delete res.data.userc.name;
}
}else{
uni.hideLoading();
this.$util.msg(res.msg);
return;
}
},
//重新上传图片调此方法
yesUpload(data){
uni.uploadFile({
url: this.CDN + this.imgaction,
filePath: this.tempAvatar,
name: 'pic1',
formData: data, //顺带整个表单对象传给服务端
success: (res) => {
const resultData = JSON.parse(res.data)
if(resultData.status === 200){
uni.hideLoading();
this.$util.msg(resultData.msg);
this.isaction = this.isdel = false;
if(resultData.data.renz){
this.data.renz = resultData.data.renz;
this.data.renz.khyh = resultData.hang;
this.data.renz.khhuser = resultData.hangzh;
}
if(resultData.data.userc){
this.data.userc = resultData.data.userc;
this.data.userc.shname = resultData.data.userc.name;
delete resultData.data.userc.name;
}
}else{
uni.hideLoading();
this.$util.msg(resultData.msg);
return;
}
}
})
}
}
}

后端

uniapp实现表单提交带图片上传 在做表单提交的时候,我们可能面临有图片上传,放在原生的html就好解决,form标签加上_上传_03

file
* @return
* @throws Exception
*/
@PostMapping("/filesUpload")
public R uploadFile(FormDataReq f, @RequestParam("file") MultipartFile file, @RequestParam(name = "businessType", required = true) String businessType) {
return R.ok("文件上传成功!", fileService.uploadPic(file, businessType));
}

子组件

<!-- 上传图片 -->
<template>
<view class='m-upload'>
<view class="label">
<text>{{label}}</text>
</view>
<view class="image">
<view class="image-list" v-for="item in imageList" :key="item.id">
<image v-if="!previewFlag" class="delete" src="/static/upload/delete.png" @click="tapDelete(item.id)">
</image>
<image class="image-data" :src="item.path" mode="aspectFill" @click="tapPreview(item.path)"></image>
</view>
<image v-if="!previewFlag" class="upload-btn-icon" src="/static/upload/upload.png"
@click="tapUpload(businessType)"></image>

<!-- 确定上传到服务器 -->
<button type="primary" @click="submitImg(businessType)">{{businessType}}</button>
</view>
</view>
</template>

<script>
export default {
props: {
label: {
type: String,
default: '上传图片'
},
businessType: {
type: String,
default: '01' //业务类型 01-考勤打卡 02-审批 03-到点留痕
},
previewFlag: {
type: Boolean,
default: false //预览模式不显示删除图标和上传图标
},
//初始显示数据
initlist: {
type: Array,
default: function() {
return [];
}
}
},
data() {
return {
imgNum: 0, //一共选中了多少张照片,用来限制本次最大上传数量
imageList: [],
serverUrl: "http://127.0.0.1:8080/file/filesUpload?businessType=", //要上传的图片的服务器地址
}
},
created() {

},
//页面渲染完成
mounted() {
for (let item of this.initlist) {
let obj = {
...item,
}
this.imageList.push(obj);
}
},
watch: {
initlist(nVal, oVal) {
for (let item of nVal) {
let obj = {
...item,
}
this.imageList.push(obj);
}

},
},
/**
* 计算属性
*/
computed: {

},
methods: {
tapDelete(id) {
let that = this;
//console.log(`删除${id}`);
//先移除显示的图片,在删除服务器端的图片
let images = that.imageList;
let indexImage = images.findIndex(n => n.id == id);
if (indexImage != -1) {
that.imageList.splice(indexImage, 1); //删除当前数组对象

//调用接口,删除图片
console.log('删除图片', id);
that.$emit('myEvent', that.imageList)
}
},
tapPreview(path) {
console.log(`当前图片${path}`);
let images = [];
for (let item of this.imageList) {
images.push(item.path);
}
// 预览图片
uni.previewImage({
current: path,
urls: images,
indicator: 'default',
loop: true,
});

},

tapUpload() {
let that = this;

uni.chooseMessageFile({
count: 9, //默认9
sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
success: function(res) {
// 遍历要上传的图片临时地址,进行上传
for (let item of res.tempFiles) {

that.imageList.push({
path: item.path,
})



// 判断本次最多上传多少照片
that.imgNum++;
if (that.imgNum > 9) {
that.imgNum = 9;
uni.showToast({
icon: "none",
title: "上传的图片最多不能超过9张",
});
return;
}

console.log("that.imageList", that.imageList)
that.$emit('myEvent', that.imageList)
}
}
});
},

// 确定上传图片,传到服务器
submitImg(businessType) {
console.log("businessType->", businessType)
let that = this;
// let token = uni.getStorageSync(TOKEN_KEY) || ''

let token =
"eyJhbGciOiJIUzI1NiJ9.eyJtYW5nZUNvbSI6Ijg2MjEiLCJyb2xlS2V5IjoibnFyb2xlIiwiY29tQ29kZSI6Ijg2MjEwMDAwMDAwMDAwMDAxIiwidXNlcklkIjoiemhhbmdzYW4iLCJpYXQiOjE2NTI1MzAyMjIsImV4cCI6MTY1MzczOTgyMn0.F-L-r2f4PkmgBaKkRp1GSo6Jerp-oHDpCr2HI4bdJ-M";
// 遍历要上传的图片临时地址,进行上传
that.imageList.map((val) => {
console.log("val-》", val)
uni.uploadFile({
url: that.serverUrl + businessType, //服务器地址
filePath: val.path, //存在本地要上传的临时图片地址
name: "file", //名字可以随便写
header: {
Authorization: "Bearer " + token,
"Content-Type": "multipart/form-data",
},
formData: {
execId: "execId",
record: "record2",
num: "num3",
},
success(res) {

//上传成功的回调函数
console.log(res, "上传成功");
uni.showToast({
icon: "none",
title: "上传成功",
});

},
fail(res) {
console.log(res, "上传失败");
// that.imageList.splice(indexImage, 1); //删除当前数组对象
uni.showToast({
icon: "none",
title: "上传失败",
});
},

});

});
},

}
}
</script>

<style lang="scss" scoped>
.m-upload {

.label {
padding: 20rpx;
background-color: #eeeeee;
font-size: 28rpx;
font-weight: bold;
color: #303133;
}

.image {
display: flex;
flex-wrap: wrap;
background-color: #FFFFFF;
padding: 20rpx;

.image-list {
position: relative;

.delete {
position: absolute;
z-index: 10;
width: 40rpx;
height: 40rpx;
top: 0;
right: 0;
}

.image-data {
width: 216rpx;
height: 216rpx;
padding: 10rpx 10rpx 0 10rpx;
}

// .upload-progress {
// width: 176rpx;
// padding: 0 10rpx;
// position: absolute;
// z-index: 20;
// height: 20rpx;
// left: 20rpx;
// bottom: 140rpx;
// }

// .upload-mask {
// position: absolute;
// z-index: 19;
// width: 216rpx;
// height: 216rpx;
// top: 10rpx;
// left: 10rpx;
// background-color: #000000;
// opacity: 0.6;
// }
}

.upload-btn-icon {
width: 216rpx;
height: 216rpx;
padding: 10rpx 10rpx 0 10rpx;
}
}
}
</style>

父组件

<template>
<view class="page">
<m-file-upload @myEvent="getMsg" :label="label" :previewFlag="previewFlag" :initlist="list"
:businessType="businessType"></m-file-upload>
</view>
</template>

<script>
export default {
data() {
return {
previewFlag: false, //是否属于预览模式 true-预览模式 false-上传模式
label: '上传图片',
businessType: '02', //业务类型 01-考勤打卡 02-审批 03-到点留痕
list: [{
id: 1,
path: 'http://localhost:8080/f/20220514154136.png',
businessType: '01' //业务类型 01-考勤打卡 02-审批 03-到点留痕
},
{
id: 2,
path: 'http://localhost:8080/f/20220514154235.png',
businessType: '02' //业务类型 01-考勤打卡 02-审批 03-到点留痕
},
{
id: 3,
path: 'http://localhost:8080/f/20220514154638.png',
businessType: '03' //业务类型 01-考勤打卡 02-审批 03-到点留痕
}
],
}
},
onLoad() {

},
methods: {
getMsg(res) {
console.log("res",res)
}
}
}
</script>

<style scoped>

</style>