本文讲解将以实际开发项目中后台添加用户模块中使用到的Layui异步文件上传以及上传图预览功能为例
如果不想Listen Talk只想Show Me Code的话直接拉到文章最后
我将贴上添加用户模块完整的模版文件和控制器相应方法代码
首先贴张图看一下实际效果:
此模块使用的是Layui的样式,接触过Layui的应该知道Layui自带的文件上传功能无法随表单其他元素一起提交给服务器,所以这里需要用到异步上传,基本思路是使用Layui的文件上传控件然后再添加一个value为空的img标签用于显示预览图和一个隐藏域用于提交文件路径信息,文件上传使用Layui.upload上传接口,其中的url字段填我们控制器中自己写的接口即可,在控制器中我们对图片格式、大小等进行验证后传入具体目录后获取路径并返回,Layui在获取到路径信息回调后即可将img的src赋值以显示预览图,并且将隐藏域value赋值从而实现路径信息和表单其他元素一起提交至服务器,说了这么多,下面贴出这些模块的代码片以供参考:
①图片上传+预览图+隐藏域
<div class="layui-form-item">
<label class="layui-form-label" for="icon">头像</label>
<div class="layui-input-inline">
<div class="site-demo-upbar layui-input-inline">
<input type="file" name="iconupload" lay-type="images" class="layui-upload-file" accept="image/*" id="iconupload">
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">头像预览</label>
<div class="layui-input-inline"><img style="width:150px;" id="icon_preview" src=""></div>
</div>
<input type="hidden" name="icon" id="icon" value="">
②Layui.upload接口以及回调
layui.upload({
url: '{:url(\'index/user/iconupload\')}' //上传接口
,success: function(res){
if(res.status==100)
layer.alert(res.message, {icon: 6},function (thiswindow) {
$('#icon_preview').attr('src',res.url);
$('#icon').val(res.url);
layer.close(thiswindow);
});
else
layer.alert(res.message, {icon: 5},function (thiswindow) {
$('#icon_preview').attr('src',res.url);
$('#icon').val(res.url);
layer.close(thiswindow);
});
}
});
③控制器iconupload方法
public function iconupload()
{
$icon = Request::file('iconupload');
$info = $icon->validate([
'size'=>10240000,
'ext'=>'bmp,jpg,png,tif,gif,pcx,tga,exif,fpx,svg,psd,cdr,pcd,dxf,ufo,eps,ai,raw,WMF,webp'
])->move('uploads/usericon/');
if($info)
{
$url = "\\uploads\\usericon\\".$info->getSaveName();
return json(['status'=>100,'message'=>'上传成功','url'=>$url]);
}
else
{
return json(['status'=>-200,'message'=>$icon->getError(),'url'=>'']);
}
}
在完成以上操作后即实现了异步上传+预览图,并可以将上传图片路径信息同表单其他元素一起提交至服务器
此例为图片上传,如果想要上传其他文件,你需要自己限定上传文件的后缀以及上传按钮上的文字
文件后缀需要修改input标签中的lay-ext:
<div class="layui-form-item">
<label class="layui-form-label" for="appupload"><span class="x-red">*</span>上传安装包</label>
<div class="layui-input-inline">
<div class="site-demo-upbar layui-input-inline">
<input type="file" lay-type="file" name="appupload" lay-ext="apk" class="layui-upload-file" accept=".apk" id="appupload">
</div>
</div>
<div class="layui-form-mid layui-word-aux">
<span class="x-red" id="tip" style="display:none">已成功上传</span>
</div>
</div>
按钮文字需要修改Layui上传接口,在里面加入title字段:
layui.upload({
url: '{:url(\'index/app/androidupload\')}' //上传接口
,title: '上传安装包'
,success: function(res){ //上传成功后的回调
console.log(res);
if(res.status==100)
layer.alert(res.message, {icon: 6},function (thiswindow) {
$('#position').val(res.url);
$('#tip').show();
layer.close(thiswindow);
});
else
layer.alert(res.message, {icon: 5},function (thiswindow) {
layer.close(thiswindow);
});
}
});
此例为安装包上传模块,效果如下:
下面贴出添加用户模块完整的模板文件和相应控制器方法代码
①Html模版文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
添加用户
</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" href="/static/css/x-admin.css" media="all">
</head>
<body>
<div class="x-body">
<form enctype="multipart/form-data" id="useraddinfo" class="layui-form" action="{:url('user/doEdit')}" method="post">
<div class="layui-form-item">
<label for="nickname" class="layui-form-label">
<span class="x-red">*</span>昵称
</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="nickname" name="nickname" required="" placeholder="请输入昵称" lay-verify="nickname">
</div>
<div class="layui-form-mid layui-word-aux">
<span class="x-red">*</span>只能使用中文,字母,部分字符
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" for="icon">头像</label>
<div class="layui-input-inline">
<div class="site-demo-upbar layui-input-inline">
<input type="file" name="iconupload" lay-type="images" class="layui-upload-file" accept="image/*" id="iconupload">
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">头像预览</label>
<div class="layui-input-inline"><img style="width:150px;" id="icon_preview" src="/static/default_images/user_default_image.jpg"></div>
</div>
<div class="layui-form-item">
<label for="mobile" class="layui-form-label"><span class="x-red">*</span>手机号</label>
<div class="layui-input-inline">
<input type="number" class="layui-input" id="mobile" name="mobile" placeholder="请输入手机号" lay-verify="mobile" required="">
</div>
<div class="layui-form-mid layui-word-aux">
<span class="x-red">*</span>请填写真实手机号,用户唯一凭证
</div>
</div>
<div class="layui-form-item">
<label for="password" class="layui-form-label"><span class="x-red">*</span>密码</label>
<div class="layui-input-inline">
<input type="password" class="layui-input" required="" id="password" name="password" lay-verify="pass" placeholder="请输入密码">
</div>
<div class="layui-form-mid layui-word-aux">
<span class="x-red">*</span>请输入6-16位的密码
</div>
</div>
<div class="layui-form-item">
<label for="mobile" class="layui-form-label"><span class="x-red">*</span>性别</label>
<label class="radio-inline">
<input type="radio" name="sex" id="sex_men" value="男" title="男">
</label>
<label class="radio-inline">
<input type="radio" name="sex" id="sex_women" value="女" title="女">
</label>
</div>
<div class="layui-form-item">
<label for="group" class="layui-form-label"><span class="x-red">*</span>用户组</label>
<div class="layui-input-inline">
<select name="user_group" id="group" class="layui-input" required="">
<option value="">请选择用户组</option>
{volist name="grouplist" id="group"}
<option value="{$group.id}">{$group.name}</option>
{/volist}
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="x-red">*</span>用户状态</label>
<label class="radio-inline">
<input type="radio" name="status" id="status_1" value="1" title="正常" checked>
</label>
<label class="radio-inline">
<input type="radio" name="status" id="status_0" value="0" title="封禁">
</label>
</div>
<input type="hidden" name="icon" id="icon" value="\static\default_images\user_default_image.jpg">
<div class="layui-form-item">
<button type="button" id="addbtn" class="layui-btn">确认添加</button>
</div>
</form>
</div>
<script src="/static/lib/layui/layui.js" charset="utf-8">
</script>
<script src="/static/js/x-layui.js" charset="utf-8">
</script>
<script type="text/javascript">
layui.use(['form','layer','upload'], function(){
$ = layui.jquery;
var form = layui.form()
,layer = layui.layer;
//图片上传接口
layui.upload({
url: '{:url(\'index/user/iconupload\')}' //上传接口
,success: function(res){ //上传成功后的回调
console.log(res);
if(res.status==100)
layer.alert(res.message, {icon: 6},function (thiswindow) {
$('#icon_preview').attr('src',res.url);
$('#icon').val(res.url);
layer.close(thiswindow);
});
else
layer.alert(res.message, {icon: 5},function (thiswindow) {
$('#icon_preview').attr('src',res.url);
$('#icon').val(res.url);
layer.close(thiswindow);
});
}
});
form.verify({
nikename: function(value){
if(value.length < 5){
return '昵称至少得5个字符啊';
}
}
,pass: [/(.+){6,12}$/, '密码必须6到12位']
});
$('#addbtn').on('click',function () {
var formData = new FormData();
formData.append("nickname",$('#nickname').val());
formData.append("mobile",$('#mobile').val());
formData.append("password",$('#password').val());
formData.append("user_group",$('#group').val());
formData.append("sex",$("input[name='sex']:checked").val());
formData.append("status",$("input[name='status']:checked").val());
formData.append("icon",$('#icon').val());
$.ajax(
{
type:'post',
url: "{:url('index/user/doadd')}",
data: formData,
contentType: false,
cache:false,
processData : false,
beforeSend: function () {
$("#addbtn").attr({ disabled:true });
},
success: function(returndata){
$("#addbtn").attr({ disabled:false });
if(returndata.status==1)
layer.alert(returndata.message, {icon: 6},function (thiswindow) {
parent.location.reload();
layer.close(thiswindow);
});
else
layer.alert(returndata.message, {icon: 5},function (thiswindow) {
layer.close(thiswindow);
});
},
error: function () {
$("#addbtn").attr({ disabled:false });
layer.alert('请求错误.请稍后再试', {icon: 5},function (thiswindow) {
layer.close(thiswindow);
});
}
}
)
})
})
</script>
</body>
</html>
这里预览图和隐藏域都有默认值的原因是如果用户不上传头像也有一个默认头像
②控制器相应方法
public function useradd()
{
$groupList = Db::table('group')->where('status','=',1)->all();
$this->view->assign('grouplist',$groupList);
return $this->view->fetch();
}
public function doadd()
{
if(!Request::isAjax())
return $this->error('请求非法');
$addinfo = Request::param();
$validate = new Validate();
$validate->rule(['nickname|昵称'=>'require|max:20|min:1','mobile|手机号'=>'require|mobile|unique:user',
'sex|性别'=>'require', 'user_group|用户组'=>'require','status|状态'=>'require',
'password|密码'=>'require|min:6|max:16|alphaDash']);
$checkres = $validate->check($addinfo);
if(!$checkres)
return ['status'=>-1,'message'=>$validate->getError()];
$nowtime = time();
$addinfo['password'] = md5($addinfo['password']);
$addinfo['create_time'] = $nowtime;
$addinfo['update_time'] = $nowtime;
$addresult = Db::table('user')->insert($addinfo);
if($addresult)
return ['status'=>1,'message'=>'用户添加成功'];
else
return ['status'=>-2,'message'=>'数据库错误'];
}
public function iconupload()
{
$icon = Request::file('iconupload');
if($icon)
{
$info = $icon->validate([
'size'=>10240000,
'ext'=>'bmp,jpg,png,tif,gif,pcx,tga,exif,fpx,svg,psd,cdr,pcd,dxf,ufo,eps,ai,raw,WMF,webp'
])->move('uploads/usericon/');
if($info)
{
$url = "\\uploads\\usericon\\".$info->getSaveName();
return json(['status'=>100,'message'=>'上传成功','url'=>$url]);
}
else
{
return json(['status'=>-200,'message'=>$icon->getError(),'url'=>'\static\default_images\user_default_image.jpg']);
}
}
}