Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】


Posted in PHP onMay 08, 2019

本文实例讲述了Thinkphp5+plupload实现支持实时预览的图片上传功能。分享给大家供大家参考,具体如下:

今天和大家分享一个国外的图片上传插件,这个插件支持分片上传大文件。其中著名的七牛云平台的jssdk就使用了puupload插件,可见这个插件还是相当牛叉的。

这个插件不仅仅支持图片上传,还支持大多数文件的上传,例如视频文件,音频文件,word文件等等,而且大文件都采用分片上传的机制。

Plupload有以下功能和特点:

1、拥有多种上传方式:HTML5、flash、silverlight以及传统的<input type=”file” />。Plupload会自动侦测当前的环境,选择最合适的上传方式,并且会优先使用HTML5的方式。所以你完全不用去操心当前的浏览器支持哪些上传方式,Plupload会自动为你选择最合适的方式。

2、支持以拖拽的方式来选取要上传的文件

3、支持在前端压缩图片,即在图片文件还未上传之前就对它进行压缩

4、可以直接读取原生的文件数据,这样的好处就是例如可以在图片文件还未上传之前就能把它显示在页面上预览

5、支持把大文件切割成小片进行上传,因为有些浏览器对很大的文件比如几G的一些文件无法上传。

下面就介绍一个tp5整合plupload图片上传插件的小案例,希望给大家带来一点小帮助。

一、案例目录结构

Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】

二、Index.php控制器方法

<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
class Index extends Controller{
  public function index(){
    $rootUrl = $this->request->root(true); //ROOT域名
    $rootUrl = explode('index.php',$rootUrl)[0];
    //模板资源变量分配
    foreach (config('TMPL_PARSE_STRING') as $key => $value) {
      $this->view->assign('_'.$key,$rootUrl.$value);
    }
    return $this->fetch();
  }
  //图片上传方法
  public function upload_images(){
    if($this->request->isPost()){
      //接收参数
      $images = $this->request->file('file');
      //计算md5和sha1散列值,TODO::作用避免文件重复上传
      $md5 = $images->hash('md5');
      $sha1= $images->hash('sha1');
      //判断图片文件是否已经上传
      $img = Db::name('picture')->where(['md5'=>$md5,'sha1'=>$sha1])->find();//我这里是将图片存入数据库,防止重复上传
      if(!empty($img)){
        return json(['status'=>1,'msg'=>'上传成功','data'=>['img_id'=>$img['id'],'img_url'=>$this->request->root(true).'/'.$img['path']]]);
      }else{
        // 移动到框架应用根目录/public/uploads/picture/目录下
        $imgPath = 'public' . DS . 'uploads' . DS . 'picture';
        $info = $images->move(ROOT_PATH . $imgPath);
        $path = 'public/uploads/picture/'.date('Ymd',time()).'/'.$info->getFilename();
        $data = [
          'path' => $path ,
          'md5' => $md5 ,
          'sha1' => $sha1 ,
          'status' => 1 ,
          'create_time' => time() ,
        ];
        if($img_id=Db::name('picture')->insertGetId($data)){
          return json(['status'=>1,'msg'=>'上传成功','data'=>['img_id'=>$img_id,'img_url'=>$this->request->root(true).'/'.$path]]);
        }else{
          return json(['status'=>0,'msg'=>'写入数据库失败']);
        }
      }
    }else{
      return ['status'=>0,'msg'=>'非法请求!'];
    }
  }
}

三、index.html页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>tp5+plupload图片上传</title>
</head>
<body>
<!-- production -->
<!--<script type="text/javascript" src="./plupload.full.min.js"></script>-->
<!-- debug-->
<script type="text/javascript" src="{$_plupload}/moxie.js"></script>
<script type="text/javascript" src="{$_plupload}/plupload.dev.js"></script>
<script type="text/javascript" src="{$_plupload}/jquery.min.js"></script>
<style>
  ul{
    list-style:none;
  }
  #file-list {overflow: hidden;padding-left: initial;}
  #file-list li {
    width:160px;
    float: left;
    height:200px;
    position: relative;
    height: inherit;
    margin-bottom: inherit;
  }
  #file-list li a {
    width:150px;
    height:150px;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    margin:0 auto;
    border:1px solid #ccc;
    padding: 5px 5px 5px 5px;
  }
  .close{
    background-image: url("{$_plupload}/close.png");
    width: 30px;
    height: 30px;
    background-size: contain;
    position: absolute;
    right: 2%;
    top: 0;
  }
  #file-list li a img {max-width:100%;max-height: 100%;}
  .progress{
    position: absolute;
    background-color: rgba(4, 4, 4, 0.53);
    color: #fff;
    padding: 3px 3px 3px 3px;
    border-radius: 10%;
  }
</style>
<input type="hidden" id="images_upload" name="images" value=""/>
<div id="container">
  <button class="btn btn-primary" type="button" id="pickfiles" style="height: 30px;line-height: 8px;">选择图片</button>
  <button class="btn btn-primary" type="button" id="uploadfiles" style="display: none">开始上传</button>
  <ul id="file-list">
  </ul>
</div>
<script type="text/javascript">
  //调用例子
  var uploader = new plupload.Uploader({
    runtimes : 'html5,flash,silverlight,html4',//上传方式顺序优先级
    browse_button : 'pickfiles',//选择图片按钮id
    container: document.getElementById('container'),//容器
    url : "{:url('Index/upload_images')}",//服务器接口地址
    flash_swf_url : "{$_plupload}/Moxie.swf",
    silverlight_xap_url : "{$_plupload}/Moxie.xap",
    multi_selection: true,//false为单图上传,true为多图上传
    filters : {
      max_file_size : '100mb',//限制文件上传大小
      mime_types: [
        {title : "Image files", extensions : "jpg,gif,png"},//限制文件上传格式
      ]
    },
    init: {
      //init事件发生后触发
      PostInit: function() {
        //document.getElementById('filelist').innerHTML = '';
        document.getElementById('uploadfiles').onclick = function() {
          uploader.start();
          return false;
        };
      },
      FilesAdded: function(up, files) {//文件选择之后的触发的方法
        var len = len = files.length;
        for(var i = 0; i<len; i++){
          var file_name = files[i].name; //文件名
          var file_size = files[i].size;//文件大小
          //构造html来更新UI
          //var html = '<li id="file-' + files[i].id +'"><p class="file-name">' + file_name + '(' + plupload.formatSize(file_size) + ')' + '</p><p class="progress"></p></li>';
          var html = '<li id="file-' + files[i].id +'"><span class="close"></span></li>';
          $(html).appendTo('#file-list');
          !function(i){
            previewImage(files[i],function(imgsrc){
              $('#file-'+files[i].id).append('<a><img src="'+ imgsrc +'" /><span class="progress">12</span></a>');
            })
          }(i);
          $("#uploadfiles").trigger('click');
        }
        /*plupload.each(files, function(file) {
         document.getElementById('filelist').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></div>';
         });*/
      },
      UploadProgress: function(up, file) {//上传过程中调用的方法
        //document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
        $('#file-'+file.id +" .progress").html(file.percent + "%");
      },
      FileUploaded : function (up,file,res) {//文件上传完成后
        console.log(res.response);
        var data = JSON.parse(res.response).data;
        $('#file-'+file.id).children('.close').attr('img_id',data.img_id);
        var img = $("#images_upload");
        var str = img.val();
        if(str == ''){
          str = data.img_id;
        }else{
          str += ','+data.img_id;
        }
        img.val(str);
      },
      Error: function(up, err) {
        //document.getElementById('console').appendChild(document.createTextNode("\nError #" + err.code + ": " + err.message));
      }
    }
  });
  //plupload中为我们提供了mOxie对象
  //有关mOxie的介绍和说明请看:https://github.com/moxiecode/moxie/wiki/API
  //file为plupload事件监听函数参数中的file对象,callback为预览图片准备完成的回调函数
  function previewImage(file,callback){
    if(!file || !/image\//.test(file.type)) return; //确保文件是图片
    if(file.type=='image/gif'){ //gif使用FileReader进行预览,因为mOxie.Image只支持jpg和png
      var gif = new moxie.file.FileReader();
      gif.onload = function(){
        callback(gif.result);
        gif.destroy();
        gif = null;
      };
      gif.readAsDataURL(file.getSource());
    }else{
      var image = new moxie.image.Image();
      image.onload = function() {
        image.downsize( 150, 150 );//先压缩一下要预览的图片,宽300,高300
        var imgsrc = image.type=='image/jpeg' ? image.getAsDataURL('image/jpeg',80) : image.getAsDataURL(); //得到图片src,实质为一个base64编码的数据
        callback && callback(imgsrc); //callback传入的参数为预览图片的url
        image.destroy();
        image = null;
      };
      image.load( file.getSource() );
    }
  }
  uploader.init();
  //移除图片
  $("#file-list").on('click',".close",function(){
    var img_id = $(this).attr("img_id");
    var img = $("#images_upload");
    var items=img.val().split(",");
    var index = items.indexOf(img_id);
    items.splice(index,1);//删除元素
    img.val(items.join(','));
    $(this).parent().remove();
  });
</script>
</body>
</html>

Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】

如果想研究插件源码的朋友,可以看这个文件,其中大部分都已经注释了。

Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】

最终效果就是这样了。

 

Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】

如果对tp5不太熟悉的朋友,建议直接配置虚拟域名,将项目目录绑定到/tp5/public/目录。

案例源码:https://github.com/BlueSimle/thinkphp5-plupload  (如果对你有帮助,请给个star哦。如果有什么疑问,请留言)

希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。

PHP 相关文章推荐
php中使用cookie来保存用户登录信息的实现代码
Mar 08 PHP
探讨:web上存漏洞及原理分析、防范方法
Jun 29 PHP
php 批量添加多行文本框textarea一行一个
Jun 03 PHP
PHP开发框架Laravel数据库操作方法总结
Sep 03 PHP
PHP常用处理静态操作类
Apr 03 PHP
PHP创建文件,并向文件中写入数据,覆盖,追加的实现代码
Mar 25 PHP
PHP Ajax JavaScript Json获取天气信息实现代码
Aug 17 PHP
Yii2 加载css、js 载静态资源的方法
Mar 10 PHP
利用ajax和PHP实现简单的流程管理
Mar 23 PHP
关于PHP中协程和阻塞的一些理解与思考
Aug 11 PHP
php apache开启跨域模式过程详解
Jul 08 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
Mar 27 PHP
PHP封装类似thinkphp连贯操作数据库Db类与简单应用示例
May 08 #PHP
php封装的pdo数据库操作工具类与用法示例
May 08 #PHP
Laravel框架查询构造器简单示例
May 08 #PHP
Laravel Validator 实现两个或多个字段联合索引唯一
May 08 #PHP
PHP+百度AI OCR文字识别实现了图片的文字识别功能
May 08 #PHP
Laravel框架模型的创建及模型对数据操作示例
May 07 #PHP
Laravel框架路由管理简单示例
May 07 #PHP
You might like
PHP+MYSQL的文章管理系统(一)
2006/10/09 PHP
php无限遍历目录示例
2014/02/21 PHP
PHP采用get获取url汉字出现乱码的解决方法
2014/11/13 PHP
PHP模拟登陆163邮箱发邮件及获取通讯录列表的方法
2015/03/07 PHP
Yii的Srbac插件用法详解
2016/07/14 PHP
详解PHP神奇又有用的Trait
2019/03/25 PHP
php和asp语法上的区别总结
2019/05/12 PHP
Laravel 6.2 中添加了可调用容器对象的方法
2019/10/22 PHP
让ie运行js时提示允许阻止内容运行的解决方法
2010/10/24 Javascript
javascript面向对象之二 命名空间
2011/02/08 Javascript
在JavaScript中监听IME键盘输入事件
2011/05/29 Javascript
javascript标签在页面中的位置探讨
2013/04/11 Javascript
jquery数组之存放checkbox全选值示例代码
2013/12/20 Javascript
jQuery判断元素是否存在的可靠方法
2014/05/06 Javascript
jQuery实现MSN中文网滑动Tab菜单效果代码
2015/09/09 Javascript
JavaScript提升性能的常用技巧总结【经典】
2016/06/20 Javascript
利用jQuery的动画函数animate实现豌豆发射效果
2016/08/28 Javascript
node.js的事件机制
2017/02/08 Javascript
js中setTimeout的妙用--防止循环超时
2017/03/06 Javascript
Bootstrap学习笔记 轮播(Carousel)插件
2017/03/21 Javascript
vue 2.0 购物车小球抛物线的示例代码
2018/02/01 Javascript
详解vue项目中实现图片裁剪功能
2019/06/07 Javascript
vue2.0项目集成Cesium的实现方法
2019/07/30 Javascript
vue瀑布流组件实现上拉加载更多
2020/03/10 Javascript
python遍历数组的方法小结
2015/04/30 Python
Python2.7.10以上pip更新及其他包的安装教程
2018/06/12 Python
深度辨析Python的eval()与exec()的方法
2019/03/26 Python
Python流程控制语句的深入讲解
2020/06/15 Python
keras model.fit 解决validation_spilt=num 的问题
2020/06/19 Python
CSS3中的常用选择器使用示例整理
2016/06/13 HTML / CSS
浅谈html5 响应式布局
2014/12/24 HTML / CSS
俄罗斯汽车零件和配件在线商店:CarvilleShop
2019/11/29 全球购物
ASP.NET中的身份验证有那些
2012/07/13 面试题
Solaris操作系统的线程机制
2012/12/23 面试题
小学生安全责任书
2014/07/25 职场文书
婚庆主持词大全
2015/06/30 职场文书