长时间没用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》