图片上传是很多网站必备的功能之一,异步多图上传也是很多初学者比较头疼的问题。所以今天我们就使用比较热门的Thinkphp和jquery File upload插件完整的开发一个多图异步上传功能。
这篇文章,我们会包含如下几个功能:
jquery File upload上传按钮优化
上传单图片,和多张图片上传预览
多张图片上传后删除,重新上传功能
Thinkphp后台图片的上传、存储
图片上传后如何在页面的显示
其中上传多张图片会放到下一篇文章,地址写好了贴:
下载
上传图片插件我们这里选用的是比较出名的jQuery File Upload插件,Github地址为:https://github.com/blueimp/jQ...
Demo在这里:https://blueimp.github.io/jQu...,这里我们选用该插件的基础功能,也就是Base版本。
后台处理图片上传程序,我们选择Thinkphp框架,也是国内非常热门的框架之一。
框架整合
先看下jquery插件下载下来后的目录文件:
这一堆文件里面,我们只需要取出js文件夹中的jquery.fileupload.js
,jquery.iframe-transport.js
,jquery.ui.widget.js
和css文件夹中的jquery.fileupload.css
即可。
在thinkphp框架的Public目录中新建css,js,img,uploads文件夹用来分别存储对应的文件。其中img文件夹需要放一张图片添加按钮图片。
uploads文件夹放置的是上传的图片目录
下面资源整合功能就大功告成了。
页面建立
单张图片应用一般在文章封面图上传,或者文章中插入图片等等。比如segemntfault的这里:
新建页面
首先在Thinkphp控制器文件夹新建IndexController.class.php
,然后新建一个add_img
方法用来显示上传图片界面,并且完成view等文件的建立。
/**
* 添加图片上传页面
*/
public function add_img()
{
$this->display();
}
HTML
下面首先在html页面引入相关js,css资源
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加图片</title>
<link rel="stylesheet" href="__PUBLIC__/css/jquery.fileupload.css">
</head>
<body>
<script src="__PUBLIC__/js/jquery-2.1.4.min.js"></script>
<script src="__PUBLIC__/js/jquery.ui.widget.js"></script>
<script src="__PUBLIC__/js/jquery.iframe-transport.js"></script>
<script src="__PUBLIC__/js/jquery.fileupload.js"></script>
</body>
</html>
这里要注意一下,除了需要引入必备的图片上传插件。还需要注意引入jquery
文件。
接下来就我们就新建一个表单。
<form action="" id="submitForm">
<div class="fileinput-button">
<div class="thumbnail" id="thumbnail">
<div class="cover">
<img src="__PUBLIC__/img/add_img.png" />
</div>
</div>
<!-- The file input field used as target for the file upload widget -->
<input id="fileupload" type="file" name="upload_img">
<div id="img_url"></div>
<!-- The container for the uploaded files -->
<div id="files" class="files"></div>
</div>
<div class="form-group">
<label for="img_name">图片名称</label>
<input type="text" name="img_name" value="" id="img_name">
<button type="button" id="submit">提交表单</button>
</div>
</form>
解释一下:
其中
fileinput-button
是十分重要的一个元素,不可缺少其中的
.thumbnail
是一个用于放图片上传后显示缩略图的地方其中的
id="fileupload"
则是浏览器默认的上传插件最后的一个
form-group
中内元素为我们需要提交的附加信息,比如图片名称或者其他信息
CSS
我们使用jquery插件的还有一个原因就是因为,浏览器默认的上传控件太丑啦。所以,优化操作必不可少。
form{ width:500px; margin:100px auto;}
.form-group{ margin-top:20px;}
.fileinput-button {
position: relative;
overflow: hidden;
border:2px dashed #E5E5E5;
text-align: center;
}
.fileinput-button .cover{ padding:50px 0;}
.fileinput-button .up-img{ width:500px;;}
.fileinput-button .up-img img{max-width: 100%;}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
font-size: 200px !important;
direction: ltr;
cursor: pointer;
}
/* Fixes for IE < 8 */
@media screen\9 {
.fileinput-button input {
filter: alpha(opacity=0);
font-size: 100%;
height: 100%;
}
}
其中第一行,第二行的form
和.form-group
是后面的附加元素,所以不重要。
之后的每一行都是用于控件美化。最后还有用于ie
浏览器的专门优化。
Javascript
下面我们直接将官方demo中的js代码copy过来用于图片上传操作
<script>
var uploadUrl = "{:U('index/upload')}";
var baseUrl = "__PUBLIC__/uploads/";
// 图片上传部分
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
$('#fileupload').fileupload({
url: uploadUrl,
dataType: 'json',
done: function (e, data) {
// 这里是图片上传完成后的代码
},
progressall: function (e, data) {
// 这里处理图片正在上传的进度
}
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
});
</script>
看下最上面的两个js全局变量uploadUrl
是上传图片的地址,baseUrl
是图片上传后除了保存在数据库中的文件路径。
这里说下为什么需要这个baseUrl
,因为我们数据库中存储的文件路径是例如201702/12/xxx.jpg
这样的日期+文件名,如果想要完整显示图片,则需要拼接上图片根目录public/upload
变为public/upload/2017/12/xxx.jpg
。这样做的好处是系统迁移十分方便,如果需要从public/uploads/
目录挪到public/images/
目录,只要修改baseUrl
即可。如果数据库存放是绝对路径,以后更改起来会十分麻烦。
fileupload
方法里面有几个参数,其中done代表文件上传完成后所执行的操作,其中data会带上服务器传输过来的一些参数。progressall是图片上传中会执行的函数。最常用的也就是这两个,其他还有例如add
添加文件时候执行的,这里不做描述。
后台处理
前面的代码完成后,点击按钮选择图片后即可上传。接下来就是后台处理图片的任务啦。
我们新建后台处理图片的方法upload()
,位于index
控制器里面
/**
* 处理图片上传
*/
public function upload(){
}
这里我们直接应用Thinkphp上传文件类来处理图片上传问题。
public function upload(){
$upload = new \Think\Upload();// 实例化上传类
$upload->maxSize = 314572800000 ;// 设置附件上传大小
$upload->exts = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
$upload->rootPath = "./Public/uploads/"; // 设置附件上传根目录
$upload->savePath = ""; // 设置附件上传(子)目录
$upload->subName = array('date','Ym/d');
// 上传文件
$info = $upload->upload();
if(!$info)
{
// 上传错误提示错误信息
$this->error($upload->getError());
}
else
{
$pic_src = $info['upload_img']['savepath'].$info['upload_img']['savename'];
$this->ajaxReturn(array("path"=>$pic_src,"status"=>1));
}
}
这里设置上传目录为当前目录下的Public
目录下的uploads
文件夹中,设置subName
为日期类型,形如年月/日/文件名
:(2017/02/xxx.jpg
)
简单配置完thinphp上传参数后,开始启用这个强大的upload()
方法上传图片。上传结果会返回到$info
变量中。如果没有返回结果,那么就表示发生了错误,我们使用$this->error($upload->getError());
将错误专项其他特定错误处理页面。否则我们向客户端返回文件上传路径和状态。
打印这个info
变量:
array (size=1)
'upload_img' =>
array (size=9)
'name' => string 'QQ截图20170212181950.png' (length=26)
'type' => string 'image/png' (length=9)
'size' => int 8637
'key' => string 'upload_img' (length=10)
'ext' => string 'png' (length=3)
'md5' => string '6ed1308e73ffd7d8be79ee1bc57bf76f' (length=32)
'sha1' => string '4641dcc5d45eb0af1f1726168cb8c9b25561c0a0' (length=40)
'savename' => string '58a0505fb4661.png' (length=17)
'savepath' => string '201702/12/' (length=10)
我们发现一个名为upload_img
(这里的upload_img
是上面html代码中file控件的name填写的值)数组中包含很多关于上传文件的信息。我们取出savepath
和savename
拼接成一个路径返回给客户端。
$pic_src = $info['upload_img']['savepath'].$info['upload_img']['savename'];
$this->ajaxReturn(array("path"=>$pic_src,"status"=>1));
同时,这个路径也是最终存入数据库的路径。
处理后台返回数据
后台图片上传完成后,也把图片在服务器上面的路径告诉了前端,现在前端还需要做的任务就是将图片预览图片显示出来。
调试后台返回数据
好,我们找到js代码中的done
这个方法,直接在里面编写图片显示的程序。首先我们先打印一下data
参数,看看里面包含了那些信息。
console.log(data);
找到其中的一个属性result
继续打印
console.log(data.result);
这次信息少了不少,但是更加有用了。发现,其中的path就是我们后台传递过来的图片路径,而status是成功状态。接下来找到html代码中存放预览图的地方。
<div class="thumbnail" id="thumbnail">
<div class="cover">
<img src="__PUBLIC__/img/add_img.png" />
</div>
</div>
把图片完整的路径丢进去即可
js操作
var path = data.result;
$("#thumbnail").html('<div class="up-img"><img style="max-width: 500px;" src="'+baseUrl+path.path+'" /></div>');
图片完美的显示了出来。在上面的js中,我们还在img外面套了一个class为up-img的div,这个是为了去控制图片位置。
生成图片路径隐藏域
接下来就是提交表单的时候了。但是还有一个问题,我们图片是显示出来了。但是提交表单时候似乎很难获取到之前上传的图片路径。所以,还需要js再次操作,将需要保存的图片路径放入input
我们在页面放一个id为img_url的div方便我们放置input
$("#img_url").html('<input type="hidden" name="img_url" value="'+ path.path +'" />');
这样,图片上传完成即可自动创建一个input隐藏域方便提交表单。
提交表单
Ajax提交数据
接下来的事情就简单多了,我们直接使用异步提交表单。
var submitUrl = "{:U('index/submit')}";
$("#submit").on('click',function () {
$.ajax({
url:submitUrl,
dataType:'json',
type:"post",
data:$("#submitForm").serialize(),
success:function (e) {
if(e.code==1){
alert('ok');
}else{
alert('fail');
}
}
});
});
创建数据库
接下来就是提交后台处理了。不过在此之前,我们新建一个数据库用来存储我们上传的文件路径。
DROP TABLE IF EXISTS `image`;
CREATE TABLE `image` (
`img_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '图片ID',
`img_url` varchar(255) NOT NULL COMMENT '图片上传路径',
`img_name` varchar(15) NOT NULL,
`create_time` int(11) NOT NULL COMMENT '图片保存时间',
PRIMARY KEY (`img_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
控制器处理代码
给出控制器代码:
public function submit()
{
$img_url = I("post.img_url");
$img_name = I("post.img_name");
$result = M("image")->data(array("img_url"=>$img_url,'img_name'=>$img_url,"create_time"=>time()))->add();
if($result){
echo json_encode(array('code'=>'1'));
}else{
echo json_encode(array('code'=>'-1'));
}
}
多张图片上传,在下篇文章,地址写好了贴。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。