表单文件域上传文件和PHP后台处理
1.html代码部分:
form表单中,chechbox,radios,文件域,下拉框等不能修改样式组件的样式,所以为了好看要先修改他们的样式
基本思路:
- 首先通过label绑定input:avatar,然后让input:avatar display:none。这样点击label就能选中文件域了
- 然后添加img和i标签,img是用来提交头像后显示在此处,而i是用来在img空的时候做遮挡层的
- 修改img和i的样式,令他们有长宽
- 最后要写一个input:hidden,这是隐藏域,用来不会在页面显示但可以随表单提交数据,这里可以把用户提交的头像保存的地址通过表单提交到后台
<form class="form-horizontal" method="post" action="/admin/users-add.php"> <div class="form-group"> <label class="col-sm-3 control-label">头像</label> <div class="col-sm-6"> <!--这里的头像框改变了文件提交按钮的默认样式--> <label class="form-image"> <input id="avatar" type="file"> <img src="http://baixiu.test/static/assets/img/default.png"> <!--隐藏域:看不见的文本框,作用是用来提交键值--> <input type="hidden" name="avatar"> <i class="mask fa fa-upload"></i> </label> </div> </div> </form>
2.js代码部分:
重点是通过FormData()这个对象来将文件转化为键和二进制的数据的格式
//关于表单文件域的使用,文件域有文件提交时也是触发change事件的。 //对input:file元素来说,提交的文件是保存在DOM属性files中,可以通过这个属性判断有没有提交,以及获得提交的元素 $('#avatar').on('change',function () { //当文件选择状态变化会执行这个事件处理函数 var $this = $(this); var files = $(this).prop('files'); //如果length为0,说明未提交文件 if(!files.length){ return ; } //拿到用户提交的文件 var file = files[0]; //异步文件上传============================================================ //FormData是HTML5新增的一个成员,专门配合ajax操作,用于在客户端和服务端之间传递二进制数据 var data = new FormData(); //保存为键值的方式 data.append('avatar',file); //通过ajax发送到服务端,这里通过未封装的ajax比较方便,用jq反而不方便 var xhr = new XMLHttpRequest(); xhr.open('POST','/admin/api/upload.php'); xhr.send(data); //将二进制形式的文件发送到后台 xhr.onload = function () { // console.log(this.responseText); $this.siblings('img').attr('src',this.responseText); $this.siblings('input').val(this.responseText); } }) </script>
3.PHP后台代码部分:
这部分首先用$_FILES接收键为avatar的数据,并了解其中每项的意义
判断是否上传成功,然后将文件保存在新地址中
返回给客户端这个地址,客户端就能通过这个地址将对应地址的图片显示在img标签中&新增数据库的用户
<?php //服务端要做的事情 //接收文件 //保存文件 //返回这个文件访问url if(empty($_FILES['avatar'])){ exit('必须上传文件'); } $avatar = $_FILES['avatar']; //传递过来的是avatar为键,二进制内容为值的键值对,但如果直接打印值的话是一个关联数组 //array(5) { // ["name"]=> // string(12) "widget_5.jpg" 客户端文件的原名称。 // ["type"]=> // string(10) "image/jpeg" 文件的 MIME 类型,需要浏览器提供该信息的支持 // ["tmp_name"]=> // string(27) "C:WindowsTempphp68F1.tmp" 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定 // ["error"]=> 和该文件上传相关的错误代码 // int(0) // ["size"]=> 已上传文件的大小,单位为字节。 // int(28658) //} //判断文件是否上传成功,只有$avatar['error']等于UPLOAD_ERR_OK,才表示上传成功 //UPLOAD_ERR_OK //值:0; 没有错误发生,文件上传成功。 //UPLOAD_ERR_INI_SIZE //值:1; 上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。 //UPLOAD_ERR_FORM_SIZE //值:2; 上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。 //UPLOAD_ERR_PARTIAL //值:3; 文件只有部分被上传。 //UPLOAD_ERR_NO_FILE //值:4; 没有文件被上传。 //值:5; 上传文件大小为0. if($avatar['error'] !== UPLOAD_ERR_OK){ exit('文件上传失败'); } //校验类型,大小 //移动文件到网站范围之外 //pathinfo() 返回一个关联数组包含有 path 的信息。比如: //Array //( // [dirname] => /testweb // [basename] => test.txt // [extension] => txt //) //这里就获取图片文件名的后缀=>jpg $ext = pathinfo($avatar['name'] , PATHINFO_EXTENSION); //uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID。 //拼接出一个新地址 $target = '../../static/uploads/img-' . uniqid() . '.' . $ext; //move_uploaded_file将上传的文件移动到新位置。若成功,则返回 true,否则返回 false。 if(!move_uploaded_file($avatar['tmp_name'] , $target)){ exit('上传失败'); } //上传成功,根据实际需要截取下地址字符串 echo substr($target,5);