PLUPLOAD插件 ━━ 上传总结(分片上传,php后端处理)

33 篇文章 5 订阅
本文介绍了如何使用Plupload 3进行文件上传,包括前端配置、事件处理和PHP后台接收分片上传的实现。前端通过设置参数、监听上传事件来控制上传过程,后台通过判断分片进行文件合并。上传成功后,通过FileUploaded事件处理服务器返回的信息。
摘要由CSDN通过智能技术生成

长时间没用plupload了,发现现在版本已经到plupload3了。
网上找了篇好文回顾一下,以下代码js和html部分亲测有效,php代码部分使用自己原来系统的,文章中的尚未测试。

plupload插件官方地址:plupload官方网站

参数,方法,设置说明文档地址:配置文档Table of Contents

前端

使用方法:

<!-- 引入plupload文件 -->
<!-- moxie用来生成图片缩略图 -->
<script src="./plupload/js/moxie.js"></script>
<script src="./plupload/js/plupload.full.min.js"></script>
<script>
    //新建一个plupload对象,并设置相应的参数
    var uploader_img = new plupload.Uploader({
        runtimes: 'html5,flash,silverlight,html4', //上传方式顺序优先级
        browse_button: 'addimg', //选择图片按钮id
		/*multipart_params:{ //传递的参数
			category:"thumb",
		},*/
        container: document.getElementById('img-box'), //容器
		//file_data_name:"fileup", //接收控件名,可以在php里使用$_FILE['fileup']接收
        url: "/index/user/uploadimg", //服务器接口地址
        flash_swf_url: "/public/assets/libs/plupload/js/Moxie.swf",
        silverlight_xap_url: "/public/assets/libs/plupload/js/Moxie.xap",
        multi_selection: true, true为多文件上传的选择方式,false为单文件上传的选择方式,仅仅为上传方式,并不限制上传总数量
		max_retries:5, //出错后尝试次数
        chunk_size: "3mb",//分片上传,每片的大小,如果php没有按照分片方式接收文件,那么这里写上0,否则文件上传失败
        filters: {
            max_file_size: '3000mb', //限制文件上传大小
            mime_types: [{
                title: "图片文件",
                extensions: "jpg,jpeg,png"//上传文件格式限制
            }, //限制文件上传格式
            ]
        },
        init: {
            //init事件发生后触发
            PostInit: function () {
                //document.getElementById('filelist').innerHTML = '';
 
            },
            FilesAdded: function (up, files) { //文件选择之后的触发的方法
                for (var i = 0; i < files.length; i++) {
                    var file_name = files[i].name; //文件名
                    var file_size = files[i].size;//文件大小
                    //构造html来更新UI
                    var html = '<div id="' + files[i].id + '" class="layui-col-md1 img-                    item draggable-element" ></div>';
                    $(html).appendTo('#elements-container');
                    //生成缩略图
                    !function (i) {
                        previewImage(files[i], function (imgsrc) {
                            $('#' + files[i].id).append('<i class="layui-icon layui-icon-close"></i><img draggable="false" οndragstart="return false" src="' + imgsrc + '" /><p class="layui-elip">' + files[i].name + '</p>');
                        })
                    }(i);
                }
                //用来拖动图片进行排序,需使用jquery-dragarrange插件
                /*$(function() {
                    $('.draggable-element').arrangeable();
                });*/
            }, 
            UploadProgress: function (up, file) { //上传过程中调用的方法
                $('#img-progress').show();
                /*var percent = file.percent;
                element.progress('img', percent + '%');*/
            },            
            FileUploaded: function (up, file, res) { //文件上传完成后,up:plupload对象,file:上传的文件相关信息,res:服务器返回的信息
                var return_msg = $.parseJSON(res.response);
                var file_info= return_msg.file_path;
                //添加表单元素
                var newimg = document.createElement('input');
                //设定input的属性
                newimg.type = 'hidden';
                newimg.name = 'imglist[]';
                newimg.value = file_info;
                newimg.class='layui-input';
                // //获取父元素
                var pNode = document.getElementById(file.id);
                pNode.appendChild(newimg);
                var input=$('#'+file.id).find('input');
                $(input).attr('name','imglist[]');
                /*Sign += 1;
                if (Sign == Sign_stop) {
                    document.getElementById('form-confirm').click();
                }*/ 
            },
            Error: function (up, err) {
                //document.getElementById('console').appendChild(document.createTextNode("\nError #" + err.code + ": " + err.message));
            }
        }
    });
    uploader_img.init();//初始化
    //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 = file.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());
        }
    }
</script>

界面:

添加前端显示的为上传按钮

<div id="img-box">
     <!--添加按钮-->
     <a href="javascript:void(0);" class="layui-btn" id="addimg">点击添加</a>
     <!--上传文件信息及删除,拖拽排序-->
     <div class="layui-row">
          <div id="elements-container">
          </div>
     </div>
     <!--上传进度条-->
     <div class="layui-progress" id="img-progress" lay-filter="img" lay-showPercent="yes">
          <div class="layui-progress-bar" lay-percent="0%"></div>
          </div>
</div>

在这里插入图片描述

添加文件之后的plupload对象
在这里插入图片描述
在这里插入图片描述
开始上传,可以选择添加之后立即上传(FilesAdded事件),也可以手动触发,方法为start();

 //上传图片
uploader_img.setOption("multipart_params", {'caseName': caseName});//设置上传附带的参数
uploader_img.start();

上传的xhr
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

PHP后台处理

上传类:

<?php
/**
 * Created by PhpStorm.
 * User: stone
 * Date: 2019.3.22
 * Time: 9:39
 */ 
namespace app\api\controller; 
 
class Upload
{
    /*
     * 流程
     * 1.移动临时文件到指定目录
     * 2.判断是否是最后一块,并进行合并
     * 3.删除临时文件及目录
     * 4.返回相关信息
     */
    private $file_path='';//上传目录
    private $temp_path='';//php文件临时目录
    private $blob_num;//第几片
    private $total_num;//总片数
    private $file_name;//文件名
    private $temp_name;//php上传的临时文件目录
    /**
     *upload constructor.
     * @access  public
     * @param   string $filePath
     * @param   string|integer $blobNum
     * @param   string|integer $totalNum
     * @param   string $fileName
     * @param   string $tempName
     *
     */
    public function __construct($filePath,$blobNum,$totalNum,$fileName,$tempName){
        $this->file_path=$filePath;
        $this->blob_num=$blobNum;
        $this->total_num=$totalNum;
        $this->file_name=$fileName;
        $this->temp_name=$tempName;
        $this->temp_path=ROOT_PATH.'public/upload/';
        $this->moveFile();
        $this->mergeFile();
 
    }
    //移动临时文件
    private function moveFile(){
        $this->touchDir();
        //将php上传的临时文件移动到临时目录
        $filename=$this->temp_path.$this->file_name.'_'.$this->blob_num;
        move_uploaded_file($this->temp_name,$filename);
    }
    //合并文件
    private function mergeFile(){
        //当前分片序号(从0开始)等于总分片数-1
        if($this->blob_num==($this->total_num-1)){
            $blob='';
            //使用fopen
            //使用file_get(put)_contents
            //先判断文件是否已经存在
            if(file_exists($this->file_path.iconv('UTF-8','GB2312',$this->file_name))){
                @unlink($this->file_path.iconv('UTF-8','GB2312',$this->file_name));
            }
            for($i=0;$i<$this->total_num;$i++){
                $blob=file_get_contents($this->temp_path.$this->file_name.'_'.$i);
                $last_path=$this->file_path.$this->file_name;
                iconv('UTF-8','GB2312',$this->file_path.$this->file_name);
                file_put_contents($last_path,$blob,FILE_APPEND);
            }
            $this->deleteTempFile();
        }
    }
    //删除上传的临时文件
    private function deleteTempFile(){
        for($i=0;$i<$this->total_num;$i++){
            @unlink($this->temp_path.$this->file_name.'_'.$i);
        }
    }
    //创建文件架
    private function touchDir(){
        //上传目录
 
        if(!file_exists($this->file_path)){
            $oldmask=umask(0);
            @mkdir($this->file_path,0777,true);
            umask($oldmask);
        }
        //临时文件上传目录
        if(!file_exists($this->temp_path)){
            @mkdir($this->temp_path,0777,true);
        }
        return;
    }
    //API返回数据GB
    public function apiReturn(){
        if($this->blob_num==($this->total_num-1)){
            //修改文件权限
            $oldmask=umask(0);
            $res=chmod($this->file_path.$this->file_name,0777);
            umask($oldmask);
            $res1=$this->file_path.$this->file_name;
            $res2=file_exists($res1);
            if($res2){
                $data['code']=2;
                $data['msg']='success';
                $data['file_path']=$this->file_path.$this->file_name;
            }
        }else{
            if(file_exists($this->temp_path.$this->file_name.'_'.$this->blob_num)){
                $data['code']=1;
                $data['msg']='waiting for all';
                $data['file_path']='';
            }
        }
        return $data; 
    } 
}

调用上传类

public function uploadImg()
{
    if ($_FILES['file']['error'] == 0) {
        $caseName = trim($this->request->param('caseName'));//获取参数
        $file_path = ROOT_PATH . '/img/';//设置文件路径
        $blob_num = $this->request->param('chunk');//当前片数
        $total_num = $this->request->param('chunks');//总片数
        $file_name = $this->request->param('name');//文件名称
        $temp_name = $_FILES['file']['tmp_name'];//零时文件名称
        $uploadClass = new Upload($file_path, $blob_num, $total_num, $file_name, $temp_name);//实例化upload类,并传入相关参数
        $data = $uploadClass->apiReturn();
        return json_encode($data);
    } else {
        $data['code'] = 0;
        $data['msg'] = 'error code:' . $_FILES['file']['error'];
        $data['file_path'] = '';
        return json_encode($data);
    }
}

上传成功后返回的信息:

在这里插入图片描述

上传成功之后,plupload对象会调用FileUploaded事件

 FileUploaded: function (up, file, res) {
    //文件上传完成后,up:plupload对象,file:上传的文件相关信息,res:服务器返回的信息
    //进行相关处理
}

上传过程中会调用UploadProgress事件

UploadProgress: function (up, file) { //上传过程中调用的方法
   $('#img-progress').show();
   var percent = file.percent;
   element.progress('img', percent + '%');
}

该方法可以用来控制进度条。

若有不足之处,敬请见谅!

==================================

参考

plupload插件上传总结(分片上传,php后端处理)
前端上传组件Plupload使用指南
Plupload上传插件中文帮助文档
前端上传组件Plupload使用说明指南

文中提到的$('.draggable-element').arrangeable();,使用了如下的插件
jquery-dragarrange
jQuery拖拽排序插件dragarrange

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值