5

图片上传是很多网站必备的功能之一,异步多图上传也是很多初学者比较头疼的问题。所以今天我们就使用比较热门的Thinkphp和jquery File upload插件完整的开发一个多图异步上传功能。

这篇文章,我们会包含如下几个功能:

  1. jquery File upload上传按钮优化

  2. 上传单图片,和多张图片上传预览

  3. 多张图片上传后删除,重新上传功能

  4. Thinkphp后台图片的上传、存储

  5. 图片上传后如何在页面的显示

其中上传多张图片会放到下一篇文章,地址写好了贴:

下载

上传图片插件我们这里选用的是比较出名的jQuery File Upload插件,Github地址为:https://github.com/blueimp/jQ...

Demo在这里:https://blueimp.github.io/jQu...,这里我们选用该插件的基础功能,也就是Base版本。

后台处理图片上传程序,我们选择Thinkphp框架,也是国内非常热门的框架之一。

框架整合

先看下jquery插件下载下来后的目录文件:

图片描述

这一堆文件里面,我们只需要取出js文件夹中的jquery.fileupload.jsjquery.iframe-transport.jsjquery.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填写的值)数组中包含很多关于上传文件的信息。我们取出savepathsavename拼接成一个路径返回给客户端。

$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'));
    }
}

多张图片上传,在下篇文章,地址写好了贴。


星空幻颖
2.7k 声望279 粉丝