今天来写写上传文件这件‘小事’
本文把我以前编写上传文件记录一下,给以后的自己备用和吐槽
需要用到的东西
- WebUpload 官网下载
- PHP
开始
引入webupload.js
<script type="text/javascript" src="./webupload/webuploader.js"></script>
然后修改样式,我的样式如下:
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.fl{
float: left;
}
.fr{
float: right;
}
label {
display: inline-block;
max-width: 100%;
margin-bottom: 5px;
font-weight: 700;
}
/*按钮*/
#picker {
width: 100px;
height: 100px;
background: #eee;
border: 1px solid #cacaca;
}
#picker .webuploader-pick {
background: #eee!important;
width: 100%!important;
height: 100%!important;
line-height: 98px;
font-size: 18px;
color: #999;
padding: 0;
}
.webuploader-element-invisible {
position: absolute !important;
clip: rect(1px 1px 1px 1px);
clip: rect(1px,1px,1px,1px);
}
.webuploader-container {
position: relative;
display: inline-block;
vertical-align: top;
}
.webuploader-pick {
position: relative;
display: inline-block;
cursor: pointer;
background: #3bb4f2;
padding: 4px 12px;
color: #fff;
text-align: center;
border-radius: 3px;
overflow: hidden;
}
/*上传列表*/
.item{
width: 300px;
height: 70px;
background: #F1F1F1;
border: 1px solid #c3c3c3;
padding: 5px 10px;
position: relative;
font-size: 14px;
color: #545454;
margin-bottom: 15px;
box-sizing: content-box;
}
.item h4{
margin: 0 0 6px;
font-size: 16px;
width: 180px;
height: 22px;
line-height: 22px;
white-space:nowrap;
-ms-text-overflow: ellipsis;
text-overflow: ellipsis;
overflow: hidden;
}
.item .progress{
height: 5px;
width: 100%;
margin: 0;
background: #aaa;
}
.item .progress-bar{
height: 100%;
background: #676565;
width: 0;
}
.item .start_upload{
}
.item .progress-txt{
margin-top:10px;
width: 200px;
height: 26px;
line-height: 26px;
overflow: hidden;
white-space:nowrap;
-ms-text-overflow: ellipsis;
text-overflow: ellipsis;
overflow: hidden;
}
.item .del_upload{
position: absolute;
right: 10px;
top: 5px;
cursor: pointer;
}
.item .del_upload:hover{
color: #333;
font-weight: 600;
}
.item .stop_upload,.start_upload,.again_upload,.continue_upload{
width: 83px;
margin-top: 10px;
height: 26px;
line-height: 26px;
text-align: center;
background: #d8d8d8;
border-radius: 3px;
display: none;
cursor: pointer;
}
.item .stop_upload:hover,.start_upload:hover,.again_upload:hover,.continue_upload:hover{
background: #cacaca;
}
.item .current{
display: block;
}
html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="default.css" rel="stylesheet" type="text/css" />
<title>上传文件</title>
</head>
<body>
<div id="imgUploadCtn">
<div class="btns">
<div id="picker">选择文件</div>
<div id="thelist" class="uploader-list"></div>
<div id="imgCtn"></div>
</div>
</div>
<script src="jquery-2.1.1.min.js"></script>
<script src="./webupload/webuploader.js"></script>
<script src="default.js"></script>
</body>
</html>
js
$(function () {
var uploader = WebUploader.create({
// swf文件路径
swf: './webupload/Uploader.swf',
// 文件接收服务端。
server: './fileUpload_set',
//后缀名验证
accept:{
title:'zip',
extensions:'zip',
mimeTypes:'.zip'
},
//分片上传
chunked:true,
//分片上传大小 这是2M
chunkSize:1024*1024*2,
//文件并发数 因为是分片有排序规则所以并发数为1
threads:1,
// 选择文件的按钮。可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#picker',
//限制文件总数
fileNumLimit:1,
// 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
resize: false
})
// 当有文件被添加进队列的时候
var $list=$('#thelist');
//随机码
var randCode='';
uploader.on( 'fileQueued', function( file ) {
$list.append( '<div id="' + file.id + '" class="item">' +
'<h4 class="info">' + file.name + '</h4>' +
'<div class="progress progress-striped active">' +
'<div class="progress-bar" role="progressbar"></div></div>'+
'<div class="state progress-txt fl" title="">等待上传...</div>' +
'<div id="' + file.id + '_del" class="del_upload fr" data-id="' + file.id + '">删除</div>' +
'<div id="' + file.id + '_stop" class="stop_upload fr" data-id="' + file.id + '">停止</div>' +
'<div id="' + file.id + '_continue" class="continue_upload fr" data-id="' + file.id + '">继续</div>' +
'<div id="' + file.id + '_upload" class="start_upload fr current" data-id="' + file.id + '">开始上传</div>' +
'<div id="' + file.id + '_again" class="again_upload fr " data-id="' + file.id + '">重新上传</div>' +
'</div>');
//删除
$list.on('click','#'+file.id+'_del',function () {
uploader.cancelFile(file);
$(this).closest('.item').remove();
});
//停止
$list.on('click','#'+file.id+'_stop',function () {
$(this).removeClass('current');
$(this).parent('.item').find('.again_upload').addClass('current');
/*uploader.stop(file);*/
uploader.cancelFile(file);
console.log(uploader.getStats());
})
//继续上传
$list.on('click','#'+file.id+'_continue',function () {
$(this).removeClass('current');
$(this).parent('.item').find('.stop_upload').addClass('current');
uploader.upload(file);
})
//开始上传
$list.on('click','#'+file.id+'_upload',function () {
$(this).removeClass('current');
$(this).parent('.item').find('.stop_upload').addClass('current');
randCode=rand(15);
uploader.upload(file);
})
//重传
$list.on('click','#'+file.id+'_again',function () {
$(this).removeClass('current');
$(this).parent('.item').find('.stop_upload').addClass('current');
randCode=rand(15);
uploader.upload(file.id);
});
});
// 文件上传过程中创建进度条实时显示。
uploader.on( 'uploadProgress', function( file, percentage ) {
var $li = $( '#'+file.id ),
$percent = $li.find('.progress .progress-bar');
// 避免重复创建
if ( !$percent.length ) {
$percent = $('<div class="progress progress-striped active">' +
'<div class="progress-bar" role="progressbar" style="width: 0%">' +
'</div>' +
'</div>').appendTo( $li ).find('.progress-bar');
}
$li.find('.state').text('上传中 - '+parseInt(percentage * 100) + '%');
$percent.css( 'width', parseInt(percentage * 100) + '%' );
});
//文件成功处理
uploader.on( 'uploadSuccess', function( file ,data) {
//data 为服务器返回的数据
//console.log(data);
if(data.status=='ok'){
if ($('#successInfo').length){
$('#successInfo').remove();
}
$('<div id="successInfo"><img src="'+data.info.img+'" alt=""><input type="hidden" name="picupload" value="'+data.info.img+'">' +
'<input type="hidden" name="fileupload" value="'+data.info.zip+'"></div>').appendTo('#imgCtn');
$( '#'+file.id ).find('.state').text('上传完成 - 100%');
subTime();
}else{
$( '#'+file.id ).find('.state').text(data.info);
};
});
//文件失败处理
uploader.on( 'uploadError', function( file ) {
$( '#'+file.id ).find('p.state').text('上传出错');
});
//上传失败获成功都会执行
uploader.on('uploadComplete',function (file) {
$('#'+file.id).find('.current').removeClass('current');
$('#'+file.id).find('.again_upload').addClass('current');
})
//文件加入队列前执行
uploader.on('beforeFileQueued', function (file) {
});
//主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次
uploader.on('uploadBeforeSend',function (file,data) {
//随机码
data.randCode=randCode;
});
//当所有文件上传完成
uploader.on('uploadFinished',function (file,data) {
});
//开始上传
$('#ctlBtn').on('click', function() {
uploader.upload();
});
// 初始化以后添加 参数
//uploader.options.formData.uid = 456789;
//随机码
function rand(i) {
var str='123456789qwertyiopasdfghjklzxcvbnm';
var strLen=str.length;
var newStr='';
Math.random()*strLen;
while(i>0){
newStr+=str[parseInt(Math.random()*strLen)];
i--;
}
return newStr;
}
var t;
function subTime() {
var i=100;
if (t){
clearInterval(t);
}
t=setInterval(function () {
$('#submit span').text('('+i+'秒后)自动提交');
if (i==0){
clearInterval(t);
$('#submit span').text('提交作品');
$('#submit').click();
return;
};
i--;
},1000);
}
})
PHP代码
<?
//文件上传
public function fileUpload_set(){
$path="./file/cookie/zip";
$imgPath="./file/cookie/img/";
$maxSize=20*1024*1024;
$exts=['zip'];
$file=new FileUploadClass();
/**
* 上传文件
* @param $mPath 保存地址
* @param string $mMaxSize 限制文件大小 单位b
* @param array $mExts 限制文件格式 array
* @return bool
*/
$msg=$file->fileSave($path,$imgPath,$maxSize,$exts);
return $this->msg($msg['status'],$msg['info']);
}
?>
PHP合并文件类
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2017-07-13
* Time: 上午 11:14
*/
class FileUploadClass
{
public $msg=[];
/**
* 上传文件
* @param $mPath 保存地址
* @param string $mMaxSize 限制文件大小 单位b
* @param array $mExts 限制文件格式 array
* @return bool
*/
public function fileSave($mPath,$mMaxSize=20*1024*1024,$mExts=[]){
if (strpos($mPath,'.')!==0){
$mPath='.'.$mPath;
}
$arr=explode('/',$mPath);
$aimUrl='';
foreach($arr as $str){
$aimUrl.=$str.'/';
if(!file_exists($aimUrl)){
mkdir($aimUrl,0777);
chmod($aimUrl,0777);
}
}
if (!file_exists($aimUrl)) {
$this->msg('error','创建目录失败');
return false;
}else{
$upload = new \org\Upload();
$upload->maxSize = $mMaxSize;
if($mExts){
$upload->exts = $mExts;
}
$upload->rootPath = $aimUrl;
$upload->driver = "Local";
$upload->saveName = ['uniqid', ''];
$info = $upload->upload();
if (!$info) {
$this->msg('error',$upload->getError());
return false;
} else {
$aimUrl=str_replace('./','/',$aimUrl);
//这里$infoyn[0]是指你上传第一个图片的信息,你如果上传N个图片就会有$infoyn[N]
if(isset($info[0]['savepath'])){
$filePath=$aimUrl . $info[0]['savepath'] . $info[0]['savename'];
}else{
$filePath=$aimUrl . $info['file']['savepath'] . $info['file']['savename'];
//获取文件格式
$ext=substr($info['file']['savename'],strrpos($info['file']['savename'],'.'));
//文件合并(分片上传)
if(!empty($_POST['chunks'])&&$_POST['chunks']!=1){
return $this->fileCombine($_POST['randCode'].$ext,$mPath,'.'.$filePath,$info['file']['savename']);
}
}
$this->msg('ok',$filePath,['fileName'=>$info['file']['name']]);
return true;
}
}
return true;
}
/**
* 文件合并
* @param $filename 上传的文件名
* @param $mPath 缓存文件夹路径
* @param $filesAddr 文件详细地址
* @param $savename 保存文件的新名称
* @return array
*/
public function fileCombine($filename,$mPath,$filesAddr,$savename){
$oldPath=$mPath.'/'.$filename;
$newPath=$mPath.'/'.$savename;
if (!file_exists($mPath)){
@mkdir($mPath,0777);
}
if(file_put_contents($oldPath,file_get_contents($filesAddr),FILE_APPEND)){
if ($_POST['chunks']==$_POST['chunk']+1){
@rename($oldPath,$newPath);
}
$this->msg('ok',$newPath);
@unlink($filesAddr);
return true;
}else{
$this->msg('error','文件合并失败');
@unlink($filesAddr);
return false;
};
}
/**
* 移动文件
* @param $filePath 文件原路径支持数组{a,b~~},字符串 "a,b,c~~"或 "a"
* @param $movePath 移动后的目录地址
* @return array
*/
function fileMove($filePath,$movePath){
if(is_string($filePath)){
$imgArr=explode(',',$filePath);
}elseif(is_array($filePath)){
$imgArr=$filePath;
}else{
$this->msg('error','文件路径只能为字符串或数组');
return false;
}
foreach ($imgArr as $vo){
if (!empty($vo)){
if(strpos($vo,'.')!==0){
$vo=".".$vo;
}
if(strpos($movePath,'.')!==0){
$movePath=".".$movePath;
}
if(!file_exists($vo)){
$this->msg('error','目标文件不存在');
return false;
}else{
$fileName=substr($vo,strrpos($vo,'/')+1);
$fileArr=explode('/',$movePath);
$aimUrl='';
foreach($fileArr as $v){
$aimUrl.=$v.'/';
if (!file_exists($aimUrl)){
if(mkdir($aimUrl,0777,true)){
$this->msg('error','创建文件夹失败');
return false;
};
//取得文件最大权限
chmod($aimUrl, 0777);
}
}
//移动文件
if(!rename($vo , $movePath.$fileName)){
$this->msg('error','移动文件失败');
return false;
};
}
}
}
$this->msg('ok',$movePath.$fileName);
return true;
}
/**
* 删除文件
* @param $dir 删除的文件路径 或 目录
* @return bool
*/
function fileDelete($dir){
if (strpos($dir,'.')!==0){
$dir='.'.$dir;
}
if (filetype($dir)=='dir'){
if ($dh=opendir($dir)){
while (($file=readdir($dh))!==false){
if($file=='.'||$file=='..'){
continue;
}
if (filetype($dir.'/'. $file)=='dir'){
if (!$this->deleteFiles($dir.'/' . $file)){
return false;
}
if(!rmdir($dir.'/'.$file)){
$this->msg('error','删除失败('.$dir.'/'.$file.')');
return false;
}
}else{
if(!unlink($dir.'/' . $file)){
$this->msg('error','删除失败('.$dir.'/'.$file.')');
return false;
}
}
}
closedir($dh);
}
}else{
if(!@unlink($dir)){
$this->msg('error','删除失败');
return false;
}
}
return true;
}
/**
* 下载文件
* @param $filePath 目标文件的路劲
* @param string $filename 下载时显示的名称
* @return bool
*/
public function fileDownload($filePath,$filename=''){
if(empty($filePath)){
$this->msg('error','缺少文件路劲');
return false;
}
if (strpos($filePath,'.')!==0){
$filePath='.'.$filePath;
}
if (is_file($filePath)) {
$length = filesize($filePath);
if ($filename){
$ext=strrchr($filePath,'.');
$showname = $filename.$ext;
}else{
$showname = ltrim(strrchr($filePath, '/'), '/');
}
$realpath =realpath($filePath);
header("Content-Description: File Transfer");
header('Content-type: application/octet-stream');
header('Content-Length:' . $length);
if (preg_match('/MSIE/', $_SERVER['HTTP_USER_AGENT'])) { //for IE
header('Content-Disposition: attachment; filename="' . rawurlencode($showname) . '"');
} else {
header('Content-Disposition: attachment; filename="' . $showname . '"');
}
header("X-Sendfile: $realpath");
exit;
} else {
$this->msg('error','文件不存在!');
return false;
}
}
public function msg($status,$info,$other=[]){
$arr=['status'=>$status,'info'=>$info];
if ($other){
$arr['other']=$other;
}
return $this->msg = $arr;
}
}
注意:
$upload = new \org\Upload();
这是就是一个上传文件的约束类你完全可以用$_FILES
来获取上传文件信息
我把文件整个分享出来:网盘下载
下载整个文件后 \org\Upload()
参数的使用:
/**
* 默认上传配置
* @var array
*/
private $config = [
// 允许上传的文件MiMe类型
'mimes' => [],
// 上传的文件大小限制 (0-不做限制)
'maxSize' => 0,
// 允许上传的文件后缀
'exts' => [],
// 自动子目录保存文件
'autoSub' => true,
// 子目录创建方式,[0]-函数名,[1]-参数,多个参数使用数组
'subName' => ['date', 'Y-m-d'],
//保存根路径
'rootPath' => './Uploads/',
// 保存路径
'savePath' => '',
// 上传文件命名规则,[0]-函数名,[1]-参数,多个参数使用数组
'saveName' => ['uniqid', ''],
// 文件保存后缀,空则使用原后缀
'saveExt' => '',
// 存在同名是否覆盖
'replace' => false,
// 是否生成hash编码
'hash' => true,
// 检测文件是否存在回调,如果存在返回文件信息数组
'callback' => false,
// 文件上传驱动e,
'driver' => '',
// 上传驱动配置
'driverConfig' => [],
];