⼩程序uploader上传⽂件并提交表单数据完整案例(接⼝框架WebAPI)⽂章⽬录
写在前⾯的话
最近⼜⾃⼰在折腾⼩程序了。最新的⼀个功能中需要实现图⽚上传。幸运的是,⼩程序扩展能⼒中有现成的⽂件上传组件uploader可以使⽤,⽽不幸的是,这个组件坑实在太多了,⽽我⼜不是单纯的⽂件上传,还需要同步上传表单数据,因此各种坑,要么就是数据传不过去,要么就是后台取不到数据,折腾了我⼀天,各种尝试,终于搞定了。前后端完整⽤法记录⼀下,希望⼤家都能快速上⼿~
uploader介绍
uploader是⼩程序WeUI组件库中的⼀个图⽚上传的组件。⼤家可以在⼩程序开发⽂档中——扩展能⼒中到相关⽤法。
这是⼀个集合了图⽚选择、上传、预览、删除的完整组件,属性定义也⽐较全⾯,可以⾃定义上传个数,有上传loading提醒和失败提醒,点击预览功能等,基本可以涵盖图⽚⽂件上传的所有功能要求。
⽤法也很简单,在json⽂件中加⼊引⽤后,在wxml⽂件中直接引⼊该组件就⾏,不需要跟⾃定义的那种⽂件上传⼀样,定义⼀堆标签和样式,⽅便多了。
官⽅⽂档有简单的使⽤案例:
1.在json中引⼊uploader组件
2.在wxml中调⽤该组件,设置属性⽅法等
<mp-uploader bindfail="uploadError"bindsuccess="uploadSuccess"select="{{selectFile}}"upload="{{uplaodFile}}"files="{{files}}"max-count="5"title="图⽚上传"tips="图⽚上传提⽰"></mp-uploader>
3.定义js中的上传⽅法
Page({
data:{
files:[{
url:'mmbiz.qpic/mmbiz_png/VUIF3v9blLsicfV8ysC76e9fZzWgy8YJ2bQO58p43Lib8ncGXmuyibLY7O3hia8sWv25KCibQb7MbJW3Q7xibNzf RN7A/0',
},{
loading:true
},{
error:true
}]
},
onLoad(){
this.setData({
selectFile:this.selectFile.bind(this),
uplaodFile:this.uplaodFile.bind(this)
})
},
selectFile(files){
console.log('files', files)
// 返回false可以阻⽌某次⽂件上传
},
uplaodFile(files){
console.log('upload files', files)
/
/ ⽂件上传的函数,返回⼀个promise
return new Promise((resolve, reject)=>{
setTimeout(()=>{
reject('some error')
},1000)
})
},
uploadError(e){
console.log('upload error', e.detail)
},
uploadSuccess(e){
console.log('upload success', e.detail)
}
});
这部分代码⾥⾯其实只需要补充uplaodFile上传⽅法调⽤后台上传图⽚的接⼝,上传功能就算完整了,这算是⼀个可⽤的完整Demo。但是实际使⽤起来,还是需要完善⼀下滴。废话不多说,直接上代码~
⽤法与代码
⼩程序前端
1.如前⽂所说,在json中引⼊组件,在页⾯调⽤
<mp-uploader bindfail="uploadError"bindsuccess="uploadSuccess"select="{{selectFile}}"upload="{{uplaodFile}}"files="{{files}}"max-count="1"title=""></ mp-uploader>
因为我只需要上传⼀张图⽚,因此设置max-count等于1。
2.在uplaodFile中,需要调⽤resolve({urls})⽅法设置上传成功状态,否则图⽚会如下图所⽰⼀直显⽰在加载中,体验很不友好,因此
先“假装”已经上传成功,等之后提交表单时再真正上传到后台。
修改uplaodFile⽅法,调⽤resolve({urls})⽅法设置上传成功状态,保存临时⽂件⽬录tempFilePaths(后⾯会⽤到)
uplaodFile(files){
console.log('upload files', files);
var that =this;
// ⽂件上传的函数,返回⼀个promise
return new Promise((resolve, reject)=>{
const tempFilePaths = pFilePaths;
that.setData(
{
filesUrl: tempFilePaths
}
)
var object ={};
object['urls']= tempFilePaths;
resolve(object);
})
},
此时图⽚会正常显⽰:
3.在表单提交⽅法中调⽤⽂件上传接⼝。
在⼩程序中,有⼀个wx.uploadFile的API⽅法,⽤来将本地资源上传到服务器,同时这个⽅法还能上传HTTP 请求中其他额外的 form data,刚好满⾜我的需求。
在通⽤的app.js⽂件中定义了uploadFile ⽅法,参数url为后台接⼝路径,filePath是本地图⽚路径,param则是需要上传的表单数据。
///上传单个⽂件
const uploadFile=(url, filePath,param)=>{
return new Promise((resolve, reject)=>{
wx.uploadFile({
url: url,//仅为⽰例,⾮真实的接⼝地址
filePath:filePath,
name:'file',
formData: param,
success(res){//上传成功
console.log(res)
//成功调⽤接⼝
resolve(JSON.parse(res.data));
},
fail(err){
console.log(err)
wx.showToast({ title:'请求失败,请刷新后重试', icon:'none'});
reject(err)
}
})
})
}
在页⾯调⽤uploadFile⽅法
submitForm:function(){
this.selectComponent('#form').validate((valid, errors)=>{
if(!valid){//数据校验
const firstError = Object.keys(errors)
if(firstError.length){
this.setData({
error: errors[firstError[0]].message
})
}
}else{//校验通过,保存
var that =this;
var url='/api/TestAPI/Add';//后台接⼝地址
var filePath=that.data.filesUrl[0];
var formData={//表单数据
'_Name': that.data.formData._Name,
'_Description': that.data.formData._Description,
'_Type': that.data.formData._Type,
'_IsVisible': that.data.formData._String(),//Boolean类型
'_Tips':JSON.stringify(that.data.formData._tips)//Array类型
};
api.uploadFile(url,filePath,formData).then((res)=>{//上图图⽚并保存表单if(res.Code =="Success"){
wx.showToast({
title:'添加成功'
});
wx.navigateBack({//返回上⼀页
delta:1,
})
}
})
.catch((err)=>{
wx.showToast({
title:'保存失败'
})
})
}
})
},
⼤家看上⾯的代码,可以发现我将formData数据重新赋值了⼀次,并且做了⼀次类型转化。为什么要这么⿇烦呢?直接⼀个formData扔过去不⾏吗?——答案是不⾏,采坑记录1,后⾯再细说。反正这么写之后图⽚和数据都可以传过去了,后台再接收就可以了。
后台接⼝ WebAPI
后台接⼝我采⽤的是WebAPI框架,可以⾃动⽣成基于RESTful标准的接⼝帮助⽂档,很⽅便使⽤。
WebApi的接⼝参数有两种形式,⼀种是基于url的[FromUri] ,另⼀种则是基于表单数据的[FromBody] 。在我之前不需要上传⽂件,直接通过post请求获取前端表单数据时,只要使⽤[FromBody]参数就可以直接将前端的Json对象转化成实体类,很简单易⽤。
然⽽使⽤
wx.uploadFile上传数据之后,不再能接收到[FromBody] 参数。因此接⼝⽅法也需要做些调整。代码如下:
[HttpPost]
[Route("Add")]
public ApiResultModel Add()
{
ApiResultModel result =new ApiResultModel(){ Code = APIReturnCode.Error.ToString(), Message ="添加失败"};
var hole =new TreeHole();
HttpContextBase context =(HttpContextBase)Request.Properties["MS_HttpContext"];//获取传统context
HttpRequestBase request = context.Request;//定义传统request对象
hole.Name = request.Form["_Name"];
hole.Description = request.Form["_Description"];
error parse newhole.Type = Guid.Parse(request.Form["_Type"]);
hole.IsAllVisible = Boolean.Parse(request.Form["_IsAllVisible"]);//获得boolean类型数据
var obk = request.Form["_tips"];
var tips = JsonConvert.DeserializeObject<JArray>(obk);//获得Array类型数据
XTransaction tran = SessionManager.Instance.BeginTransaction();
try
{
string url;
bool isUploaded =uploadImage(out url);//保存图⽚
if(!isUploaded)
{
result.Message ="上传图⽚失败";
return result;
}
hole.Id = Guid.NewGuid();
hole.CreateTime = DateTime.Now;
hole.IsDelete =false;
hole.HeadImage = url;
//保存代码(略)
result.Message ="添加成功!";
result.Code = APIReturnCode.Success.ToString();
result.Token = hole.Id.ToString();
}
catch(Exception ex)
{
if(tran !=null) tran.RollbackTransaction();
result.Message = ex.Message;
}
finally
{
tran.Dispose();
}
return result;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论