思路
- 先上传图片,再上传数据
- 图片上传到服务器文件夹下,数据库只保存路径
- 多张图片存储路径时将按分隔符路径拼接成字符串
- 微信小程序
wx.uploadFile
只能单张分别上传
前端
页面
<!--index.wxml-->
<view class="container">
<form class="question" bindsubmit="formSubmit">
<view>问题说明:</view>
<textarea class="quesText" name="quesText" placeholder="请具体描述" auto-focus="true"></textarea>
<button class="imageBtn" bindtap="chooseImage" type="primary" plain size="mini"> 上传凭证</button>
<view>
<block wx:for="{{imageList}}" wx:key="*this" >
<image class="imageIcon" data-src="{{item}}" src="{{item}}" mode="aspectFit" bindtap="previewImage"></image>
</block>
</view>
<button class="quesBtn" form-type="submit" type="primary">提交</button>
</form>
</view>
逻辑
//index.js
//获取应用实例
const app = getApp()
const url = "http://localhost:8081/"
Page({
data: {
userInfo: {}, //用户信息
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
imageList: [], //用户上传图片的临时路径
position: {}, //用户位置信息
imgpaths: [], //返回的服务器图片存放路径
date: null //用户上传时间
},
// 页面加载时调用,只会调用一次
onLoad: function () {
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
} else if (this.data.canIUse){
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
app.userInfoReadyCallback = res => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
} else {
// 在没有 open-type=getUserInfo 版本的兼容处理
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
}
// 获取当前位置
let that=this
wx.getLocation({
type: 'wgs84',
success(res) {
that.setData({
position: {
"latitude":res.latitude,
"longitude":res.longitude
}
})
}
})
},
// 表单提交事件处理
formSubmit: function (e) {
let quesText = e.detail.value.quesText
var that=this
wx.showModal({
title: '确认提交',
success: function(res) {
if(res.confirm) {
that.setData({
date:new Date()
})
if (that.data.imageList.length == 0) {
that.upLoadData(quesText)
}
else{
let proArr=[]
for (let i = 0; i < that.data.imageList.length; i++) {
proArr.push(that.uploadFile(that.data.imageList[i]))
}
Promise.all(proArr).then((res)=>{
that.upLoadData(quesText)
})
}
}
}
})
},
// 上传数据
upLoadData: function (quesText) {
let that=this
let username = that.data.userInfo.nickName
let usersex = that.data.userInfo.gender ? (that.data.userInfo.gender == 1 ? '男' : '女') : '未知'
let country = that.data.userInfo.country
let province = that.data.userInfo.province
let city = that.data.userInfo.city
let position = that.data.position
let imgpaths = that.data.imgpaths.join(";")
wx.request({
url: url + "wechatQues",
method: 'POST',
data: {
"username": username,
"usersex": usersex,
"country": country,
"province": province,
"city": city,
"quesText": quesText,
"latitude": position.latitude,
"longitude": position.longitude,
"imgpaths": imgpaths,
"date": that.data.date
},
header: {
'content-type': 'application/x-www-form-urlencoded' // 默认值
},
success: function (res) {
console.log(res.data)
that.data.imgpaths=[]
that.data.imageList=[]
wx.showToast({
title: '提交成功',
icon: 'success',
duration: 2000,
})
},
fail: function (err) {
console.log(err)
wx.showToast({
title: '提交失败',
icon: 'none',
duration: 2000,
})
}
})
},
// 上传文件
uploadFile: function (filePath){
let that=this
return new Promise((resolve,reject)=>{
wx.uploadFile({
url: url + "wechatImg",
filePath: filePath,
name: 'image',
formData: {
"username": that.data.userInfo.username,
"date": that.data.date
},
header: {
"Content-Type": "multipart/form-data"
},
success: function (res) {
console.log(res.data)
that.data.imgpaths.push(res.data)
resolve()
},
fail: function (err) {
console.log(err)
reject()
}
})
})
},
// 选择图片
chooseImage: function(e){
let that=this
wx.chooseImage({
count: 9,
sizeType: ['original','compressed'],
sourceType: ['album','camera'],
success: function(res) {
// console.log(res)
that.setData({
imageList:res.tempFilePaths
})
},
fail: function(res) {
wx.showToast({
title: '上传失败',
icon: 'none',
duration: 2000,
})
},
})
},
// 预览图片
previewImage: function (e) {
// console.log(e)
let that=this
let current = e.currentTarget.dataset.src
wx.previewImage({
urls: that.data.imageList,
current:current
})
}
})
后端
controller
- 接收图片,并返回其存储位置
@PostMapping("/wechatImg")
public String wechatImg(@RequestParam("image") MultipartFile img) throws IOException {
String path="C:/Users/lorog/Desktop/";
// String filename=img.getOriginalFilename();
String filename=new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
String suffix=img.getOriginalFilename().substring(img.getOriginalFilename().lastIndexOf("."));
String pathname=path+filename+suffix;
FileOutputStream os=new FileOutputStream(pathname);
FileCopyUtils.copy(img.getInputStream(),os);
return pathname;
}
- 接收数据,存储到数据库,其中包括图片路径
@PostMapping("/wechatQues")
public String wechatQues(@RequestParam("username") String username,
@RequestParam("usersex") String usersex,
@RequestParam("country") String country,
@RequestParam("province") String province,
@RequestParam("city") String city,
@RequestParam("quesText") String quesText,
@RequestParam("latitude") String latitude,
@RequestParam("longitude") String longitude,
@RequestParam("date") Date date ,
@RequestParam("imgpaths") String imgpaths){
Question question=new Question();
question.setUsername(username);
question.setUsersex(usersex);
question.setCountry(country);
question.setProvince(province);
question.setCity(city);
question.setQuesText(quesText);
question.setLatitude(latitude);
question.setLongitude(longitude);
question.setDate(date);
question.setImgpaths(imgpaths);
System.out.println(question);
Boolean res=dataService.addQuestion(question);
if(res){
return "uopload data success!";
}else {
return "uopload data failed!";
}
}
service
- 接口
public interface DataService {
public Boolean addQuestion(Question question);
}
- 实现
@Service
public class DataServiceImpl implements DataService {
@Autowired
private QuestionMapper questionMapper;
@Override
public Boolean addQuestion(Question question) {
questionMapper.addQuestion(question);
return true;
}
mapper
@Repository
public interface QuestionMapper extends BaseMapper<Question> {
public Boolean addQuestion(Question question);
}
model
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Question implements Serializable {
private static final long serialVersionUID = 1L;
@TableField("username")
private String username;
@TableField("usersex")
private String usersex;
@TableField("country")
private String country;
@TableField("province")
private String province;
@TableField("city")
private String city;
@TableField("quesText")
private String quesText;
@TableField("latitude")
private String latitude;
@TableField("longitude")
private String longitude;
@TableField("date")
private Date date;
@TableField("imgpaths")
private String imgpaths;
}
mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lorogy.sprongboot.demo.mapper.QuestionMapper">
<insert id="addQuestion" parameterType="com.lorogy.sprongboot.demo.model.Question" >
insert into wechat_ques values (#{username}, #{usersex}, #{country}, #{province}, #{city}, #{quesText}, #{latitude}, #{longitude}, #{date}, #{imgpaths})
</insert>
</mapper>