最近在研究做一个多图上传,大视频上传、支持断点续传的功能,发现plupload插件比较符合要求,于是进行了简单研究,有什么不对的地方还望大家指正(新手,第一次写博客。。。)。
主要使用plupload插件(plupload.full.min.js、jquery.plupload.queue.js、jquery.plupload.queue.css、zh_CN.js)、以及Sortable.js插件
效果❤:
1.
4.
1.页面部分
引入css js
<link rel="stylesheet" type="text/css" href="/js/plupload-2.3.6/js/jquery.plupload.queue/css/jquery.plupload.queue.css">
<script src="/js/jquery.min.js"></script>
<script src="/js/plupload/plupload.full.min.js"></script>
<script src="/js/plupload-2.3.6/js/jquery.plupload.queue/jquery.plupload.queue.js"></script>
<script src="/js/plupload-2.3.6/js/i18n/zh_CN.js"></script>
1.1上传成功后缩略图展示部分样式
<style>
#pic-list {
list-style-type: none;
/*position: absolute;*/
border: 2px solid #767997;
padding: 5px;
display: none;
width: 315px;
overflow: hidden;
/*margin-bottom: 100px;*/
}
#pic-list #triangle {
border: 10px solid #767997;
border-color: transparent transparent #767997 transparent;
position: absolute;
top: -20px;
left: 5px;
}
#pic-list #title {
padding-bottom: 5px;
}
#pic-list #title span {
font-weight: bold;
}
#pic-list #title b {
float: right;
}
#pic-list #title b:hover {
color: #434664;
}
#pic-list #title #hint {
color: #434664;
font-size: .7em;
padding-top: .7em;
}
#pic-list li {
position: relative;
display: inline-block;
float: left;
margin: 5px 5px 0px 0px;
font-size: 0px; /* 解决换行间隙问题 */
cursor: move;
}
#pic-list li#addBtn {
box-sizing: border-box;
width: 100px;
/*height: 100px;*/
height: 75px;
/*line-height: 90px;*/
line-height: 60px;
border: 2px dashed #CCC;
color: #CCC;
font-size: 80px;
text-align: center;
padding-bottom: 30px;
}
#pic-list li img {
box-sizing: border-box;
width: 100px;
/*height: 100px;*/
height: 75px;
border: 2px dashed #CCC;
}
#pic-list li:not(#addBtn):hover {
filter: alpha(Opacity=50);
-moz-opacity: 0.5;
opacity: 0.5;
}
#pic-list li#addBtn:hover {
border-color: #767997;
color: #767997;
}
#pic-list li b{
display: none;
position: absolute;
right: 0px;
top: 0px;
color: black;
font-size: 15px;
text-align: center;
cursor: pointer;
}
#title b{
cursor: pointer;
}
#pic-list li:not(#addBtn):hover b {
display: block;
width: 20px;
height: 20px;
}
#pic-list li:not(#addBtn):hover b:hover {
background-color: #808080;
}
#hit{
height: 18px;
}
</style>
1.2html页面核心部分
<div id="uploader">
<p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
</div>
<button id="toStop">暂停</button>
<button id="toStart">续传</button>
<!--缩略图展示部分-->
<div>
<ul id="pic-list" style="margin-top: 10px;">
<span id="triangle"></span>
<div id="title">
<b onclick="delall()">X</b>
<div id="hit"></div>
</div>
</ul>
</div>
1.3 js部分
<script type="text/javascript">
$(function() {
// Initialize the widget when the DOM is ready
var uploader = $("#uploader").pluploadQueue({
// General settings
runtimes: 'html5,flash,silverlight,html4',
url: "/admin/chunkUpload",//这里替换为你的路径
// Maximum file size
max_file_size: '10000mb',
chunk_size: '20mb',
// Specify what files to browse for
filters: [
{title: "Image files", extensions: "jpg,gif,png"},
{title: "Vedio files", extensions: "mp4,mkv"},
{title: "Zip files", extensions: "zip,avi"}
],
// Rename files by clicking on their titles 通过点击文件标题 对文件进行重命名(文件上传前,可以点击文件名称重新编辑文件名)
rename: true,
// Sort files
sortable: true,
// Enable ability to drag'n'drop files onto the widget (currently only HTML5 supports that)
dragdrop: true,
// Views to activate
views: {
list: true,
thumbs: true, // Show thumbs
active: 'thumbs'
},
// Flash settings
flash_swf_url: 'js/Moxie.swf',
// Silverlight settings
silverlight_xap_url: 'js/Moxie.xap'
});
uploader.bind('FileUploaded', function(up, file, rt) {
var data = JSON.parse(rt.response);
if(data.error==0){
$('#pic-list').show();
var url = data.info.path.replace('./','');
//判断是图片还是视频
//获取最后一个/的位置
var site = url.lastIndexOf(".");
//截取最后一个/后的值
var tp = url.substring(site + 1, url.length).toLowerCase();
var imgarr=['jpg','gif','png'];
var videoarr=['mp4','mkv'];
if(imgarr.indexOf(tp) > -1){//则包含该元素}){
//图片
var onepic = '<li><img src="这里替换为你的域名/'+url+'"><b onclick="delimg(this,false)">x</b><input type="hidden" name="" value="这里替换为你的域名/'+url+'"></li>';
//$('#title').after(onepic);
$('#pic-list').append(onepic);
}
if(videoarr.indexOf(tp) > -1){
//视频
var oneVideo='<li><video id="video-div" controls="controls" style="margin-top: 10px;max-width: 400px;width: 100%;max-height:300px;">' +
' <source src="这里替换为你的域名'+url+'" type="video/mp4" id="video">\n' +
' </video><b onclick="delimg(this,false)">x</b></li>';
//$('#title').after(oneVideo);
$('#pic-list').append(oneVideo);
}
uploader.refresh(); // 重新渲染DOM,避免在添加按钮原位置仍会响应打开文件夹
}
else{
alert("出错了");
}
});
//当上传队列中某一个文件开始上传后触发。
uploader.bind('BeforeUpload', function(uploader, file){
console.log('文件开始上传了');
//console.dir(file);
});
//当使用文件小片上传功能时,每一个小片上传完成后触发
uploader.bind('ChunkUploaded', function(uploader,file,responseObject){
console.log('-----当文件上传分片的时候打印 开始----');
//console.dir(JSON.parse(responseObject['response']));
console.log('-----当文件上传分片的时候打印 结束---');
});
$("#toStop").on('click', function () {
uploader.stop();
});
$("#toStart").on('click', function () {
uploader.start();
});
});
//单张图片删除
function delimg(o,isConfirm) {
if(!isConfirm){
if(confirm("图片删除后不可恢复,确定删除?")) {
console.log("delete");
var tgname = $(o).prev()[0].tagName
console.log($(o).prev()[0].tagName);
var src = '';
if(tgname == 'IMG'){
src =$(o).prev().attr("src");
}else{
src =$(o).prev().children().attr('src');
}
delurl = src.substring(18);//注意:此处的imgurl需要根据实际情况修改,需要减去网址域名部分,剩余部门作为参数传递
//删除图片路径
//imgpath.splice($.inArray(delurl, imgpath), 1);
$.post('/admin/uploadImage?get=delimg&imgurl=' + delurl, function (data) {
/*optional stuff to do after success */
console.log(data);
if (data == 1) {
if ($("#pic-list").children("li").length == 10) {
$("#addBtn").css("display", "block");
}
$(o).parent().remove();
}
else {
console.log(data);
}
});
}
}else{
console.log("delete all");
// /var src = $(o).prev().attr("src");
var tgname = $(o).prev()[0].tagName
console.log($(o).prev()[0].tagName);
var src = '';
if(tgname == 'IMG'){
src =$(o).prev().attr("src");
}else{
src =$(o).prev().children().attr('src');
}
delurl = src.substring(18);//注意:此处的imgurl需要根据实际情况修改,需要减去网址域名部分,剩余部门作为参数传递
//删除图片路径
imgpath=[];
$.post('/admin/uploadImage?get=delimg&imgurl=' + delurl, function (data) {
/*optional stuff to do after success */
console.log(data);
if (data == 1) {
if ($("#pic-list").children("li").length == 10) {
$("#addBtn").css("display", "block");
}
$(o).parent().remove();
}
else {
console.log(data);
}
});
}
}
// 图片全部删除
function delall() {
if(confirm("图片删除后不可恢复,确定删除?")) {
$("#pic-list").hide();
$("#pic-list li").children("b").each(function (index, el) {
delimg(el,true);
});
}
//显示添加 上传按钮
$('.plupload_buttons').show();
$('.plupload_upload_status').hide();
$('.plupload_total_file_size').html('0 b');
$('.plupload_total_status').html('0%');
$('.plupload_upload_status').html('');
}
</script>
2.后台PHP代码
//图片视频上传
function chunkUpload()
{
//封装好的plupload文件上传类,直接使用即可
require_once __DIR__.'/PluploadHandler.php';
$ph = new PluploadHandler(array(
'target_dir' => './uploads/',//上传路径
'allow_extensions' => 'jpg,jpeg,png,gif,mp4,mov,mkv,zip,avi',//允许上传格式
));
$ph->sendNoCacheHeaders();
$ph->sendCORSHeaders();
if ($result = $ph->handleUpload()) {
//图片上传路径 需做简单修改,这个可以打印出来自己看就明白了
$result['path']=str_replace('\\','/',$result['path']);
die(json_encode(array(
'error' => 0,
'info' => $result
)));
} else {
die(json_encode(array(
'error' => 1,
'error' => array(
'code' => $ph->getErrorCode(),
'message' => $ph->getErrorMessage()
)
)));
}
}
//视频图片删除
function uploadImage()
{
if ($_GET['get'] == 'delimg') {
$imgsrc = $_GET['imgurl'];
unlink($imgsrc);
echo 1;
}
}
另:这里把封装好的PluploadHandler.php代码贴出来
<?php
define('PLUPLOAD_MOVE_ERR', 103);
define('PLUPLOAD_INPUT_ERR', 101);
define('PLUPLOAD_OUTPUT_ERR', 102);
define('PLUPLOAD_TMPDIR_ERR', 100);
define('PLUPLOAD_TYPE_ERR', 104);
define('PLUPLOAD_UNKNOWN_ERR', 111);
define('PLUPLOAD_SECURITY_ERR', 105);
define('DS', DIRECTORY_SEPARATOR);
///**
// * Public interface:
// * @method void handleUpload(array $conf)
// * @method string combineChunksFor(string $file_name)
// * @method int getFileSizeFor(string $file_name)
// * @method string getTargetPathFor(string $file_name)
// * @method void sendNoCacheHeaders()
// * @method void sendCorsHeaders()
// * @method int getErrorCode()
// * @method string getErrorMessage()
// *
// */
class PluploadHandler
{
/**
* @property array $conf
*/
private $conf;
/**
* Resource containing the reference to the file that we will write to.
* @property resource $out
*/
private $out;
/**
* In case of the error, will contain error code.
* @property int [$error=null]
*/
protected $error = null;
function __construct($conf = array())
{
$this->conf = array_merge(
array(
'file_data_name' => 'file',
'tmp_dir' => ini_get("upload_tmp_dir") . DS . "plupload",
'target_dir' => false,
'cleanup' => true,
'max_file_age' => 5 * 3600, // in hours
'max_execution_time' => 5 * 60, // in seconds (5 minutes by default)
'chunk' => isset($_REQUEST['chunk']) ? intval($_REQUEST['chunk']) : 0,
'chunks' => isset($_REQUEST['chunks']) ? intval($_REQUEST['chunks']) : 0,
'append_chunks_to_target' => true,
'combine_chunks_on_complete' => true,
'file_name' => isset($_REQUEST['name']) ? $_REQUEST['name'] : false,
'allow_extensions' => false,
'delay' => 0, // in seconds
'cb_sanitize_file_name' => array($this, 'sanitize_file_name'),
'cb_check_file' => false,
'cb_filesize' => array($this, 'filesize'),
'error_strings' => array(
PLUPLOAD_MOVE_ERR => "Failed to move uploaded file.",
PLUPLOAD_INPUT_ERR => "Failed to open input stream.",
PLUPLOAD_OUTPUT_ERR => "Failed to open output stream.",
PLUPLOAD_TMPDIR_ERR => "Failed to open temp directory.",
PLUPLOAD_TYPE_ERR => "File type not allowed.",
PLUPLOAD_UNKNOWN_ERR => "Failed due to unknown error.",
PLUPLOAD_SECURITY_ERR => "File didn't pass security check."
),
'debug' => false,
'log_path' => FCPATH."error.log"
),
$conf
);
}
function __destruct()
{
$this->reset();