初学thinkphp,看到可以做文件上传就试着写了一下,用的mamp集成环境,thinkphp为3.2.3版本。
github地址:https://github.com/fanhu371328/fileUpload
一、先看一下项目的文件目录结构
1、index.php为项目的入口文件:
<?php
// 检测PHP环境
if(version_compare(PHP_VERSION,'5.3.0','<')) die('require PHP > 5.3.0 !');
// 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false
define('APP_DEBUG',True);
// 定义应用目录
define('APP_PATH','./fanhu/');
// 引入ThinkPHP入口文件
require './ThinkPHP/ThinkPHP.php';
// 亲^_^ 后面不需要任何代码了 就是如此简单
这里定义了项目的文件目录在fanhu这个文件夹下面。
2、IndexController.class.php是index控制器,代码如下:
<?php
namespace Home\Controller;
use Think\Controller;
use Think\Upload;
class IndexController extends Controller {
//文件上传
public function upload(){
//实例化上传类
$upload = new Upload();
//设置上传文件大小
$upload->maxSize = 3145728;
$upload->exts = array('pdf','doc','txt','xlsx');
$upload->savePath = './'; //上传路径在项目的根目录下的uploads文件夹
//上传成功后返回的信息
$info = $upload->upload();
if( !$info ){
$this->error($upload->getError());
} else {
$this->success("上传成功");
}
}
}
3、view 下的file.html为对应的模板文件,也就是页面视图部分,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传资料</title>
<link rel="stylesheet" href="__PUBLIC__/css/public.css">
<link rel="stylesheet" href="__PUBLIC__/css/file_upload.css">
</head>
<body>
<div class="section">
<form id="uploadForm" class="section-top" method="post" action="./upload" enctype="multipart/form-data">
<p class="file-header">上传资料</p>
<div class="upload-file">
<input type="file" name="upload[]" id="upload" />
<p>
<img src="__PUBLIC__/img/wodeshangchuan.png" /> 上传我的资料
</p>
<p>
每成功上传一份资料,可获得 <span>5</span> 积分奖励
</p>
</div>
<div class="file-content hidden">
<p>您选择的文件</p>
<ul class="file-list">
<!--文件预览-->
</ul>
<div class="clearfix">
<p>
选择<span class="file-num">5</span>个文件,共<span class="file-size">4M</span>
</p>
<p>
<img src="__PUBLIC__/img/PDF.png" />继续添加
</p>
<input type="file" name="upload[]" class="add-more" />
</div>
<input type="submit" name="submit" id="submit" value="开始上传" />
</div>
</form>
<!--上传资料提示信息-->
<div class="section-bottom">
<div>
<p class="tips-file"><img src="__PUBLIC__/img/zhuyi.png" />上传资料说明</p>
<ul>
<li>1、上传的资料需通过审核后才会发布</li>
<li>2、支持5M以内的资料文件上传</li>
<li>3、请勿在未经授权的情况下上传任何版权侵权的文档,除非文档完全由您个人创作或您得到了版权所有者的授权</li>
<li>4、为了文档能正常显示,我们支持以下格式的文档上传</li>
</ul>
</div>
<div>
<p class="tips-file"><img src="__PUBLIC__/img/zhuyi.png" />支持文件格式</p>
<ul>
<li>
<span>Microsoft office</span>
<span><img src="__PUBLIC__/img/word.png"/>doc,docx</span>
<span><img src="__PUBLIC__/img/ppt.png"/>ppt,pptx</span>
<span><img src="__PUBLIC__/img/Excel.png"/>xls,xlsx</span>
</li>
<li>
<span>文本</span>
<span><img src="__PUBLIC__/img/TXT.png"/>txt</span>
</li>
<li>
<span>Adobe PDF</span>
<span><img src="__PUBLIC__/img/PDF.png"/>pdf</span>
</li>
</ul>
</div>
</div>
</div>
</body>
<script src="__PUBLIC__/js/jquery-2.1.4.min.js"></script>
<script src="__PUBLIC__/js/file_upload.js"></script>
</html>
二、文件上传方式1—>使用form表单进行提交
;(function($) {
var files_content = []; //所有文件信息存储在这里,做文件预览用
var files_list = []; //所有file类型的input存储在这里,最后上传
var files_num = 1; //点击上传时的input个数
var size_all = "0Kb"; //文件总大小
var upload = document.querySelector('#upload');
var index = $('.file-content>div input').length;
var addMore = document.querySelectorAll('.add-more')[index-1];
var typeArr = ['doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'pdf', 'txt', 'text']; //所有支持的文件格式
var __PUBLIC__ = "/fileUpload/Public/";
//添加文件
upload.onchange = function() {
if(upload.files.length > 0) {
var fileList = upload.files;
var num = 0;
//添加文件和继续添加的共用方法
addFile(fileList,num);
}
$('.upload-file').addClass('hidden');
$('.file-content').removeClass('hidden');
//创建预览
createPreview();
allSize();
}
//创建预览
function createPreview() {
if(files_content.length == 0) {
$('.upload-file').removeClass('hidden');
$('.file-content').addClass('hidden');
} else {
var html = [];
for(var i = 0; i < files_content.length; i++) {
var item = files_content[i];
html.push(renderItem(item));
}
$(".file-list").html(html.join(''));
//文件总大小
var num = 0;
for(var i = 0; i < files_content.length; i++) {
num = num + (files_content[i].size) / 1024; //现在是kb
}
if(num >= 1024) {
size_all = (num / 1024).toFixed(2) + "M";
} else {
size_all = num.toFixed(2) + "Kb";
}
}
delate();
}
function renderItem(data) {
//文件名
var name = data.name;
var size = data.size;
//文件类型
var type = name.split('.')[1].toLowerCase();
var src = __PUBLIC__ + "img/PDF.png";
switch(type) {
case "doc":
src = __PUBLIC__ + "img/word.png";
break;
case "docx":
src = __PUBLIC__ + "img/word.png";
break;
case "ppt":
src = __PUBLIC__ + "img/ppt.png";
break;
case "pptx":
src = __PUBLIC__ + "img/ppt.png";
break;
case "xls":
src = __PUBLIC__ + "img/Excel.png";
break;
case "xlsx":
src = __PUBLIC__ + "img/Excel.png";
break;
case "txt":
src = __PUBLIC__ + "img/TXT.png";
break;
case "pdf":
src = __PUBLIC__ + "img/PDF.png";
break;
}
//文件大小
size = (size / 1024).toFixed(2) + "Kb";
//最终要展示的单个文件大小
if(parseFloat(size) >= 1024) {
size = (parseInt(size) / 1024).toFixed(2) + "M";
}
var str = '<li class="clearfix">\
<p>\
<img class="type-icon" src="' + src + '" />\
<span>' + data.name + '</span>\
</p>\
<div class="progress-content hidden">\
<progress></progress>\
<span id="progress">0%</span>\
</div>\
<span class="size">' + size + '</span>\
<img class="close-icon" name="close" src="' + __PUBLIC__ + 'img/guanguanbi.png" />\
</li>';
return str;
}
//计算文件总数和总大小
function allSize() {
//文件数
var length = files_content.length;
$('.file-num').html(length);
//文件总大小
$('.file-size').html(size_all);
}
//删除文件
function delate() {
$('.file-list li').on('click', function(e) {
if(e.target.name == 'close') {
var index = $(this).index();
//删除对应的input节点,并将input数量减1
$('.section-top input[type="file"]').eq(index).remove();
files_num--;
//重新赋值全部文件数组
var arr = [];
for(var i = 0; i < files_content.length; i++) {
if(i != index) {
arr.push(files_content[i])
}
}
files_content = arr;
//文件总大小
var num = 0;
for(var i = 0; i < files_content.length; i++) {
num = num + (files_content[i].size) / 1024; //现在是kb
}
if(num >= 1024) {
size_all = (num / 1024).toFixed(2) + "M";
} else {
size_all = num.toFixed(2) + "Kb";
}
allSize();
//重新加载预览视图
createPreview();
}
})
$('.close-icon').on('mouseover', function() {
$(this).addClass('close-icon1');
})
$('.close-icon').on('mouseout', function() {
$(this).removeClass('close-icon1');
})
}
//继续添加文件
addMore.onchange = function() {
if(addMore.files.length > 0) {
var fileList = addMore.files;
var num = 0;
addFile(fileList,num);
//添加文件完成后再创建一个input,置于现有的input之上
$('.file-content>div input').addClass('hidden');
cereateInput();
}
//创建预览
createPreview();
allSize();
}
function addFile(fileList,num) {
for(var item in fileList) {
//数组后面会自动添加两项不是我们需要的,排除出去
if(num < fileList.length) {
//对格式和大小进行判断
var type = fileList[item].name;
var flag = false;
for(var i = 0; i < typeArr.length; i++) {
if(type.indexOf(typeArr[i]) >= 0) {
flag = true; //能够匹配到一种格式就置为true
}
}
if(flag == true) {
//格式符合的再判断大小,都符合条件再添加到文件集合中
if(fileList[item].size / 1024 > 5120) {
alert("上传的文件" + fileList[item].name + "大小超过了5M!")
} else {
files_content.push(fileList[item]);
}
} else {
alert("上传的文件" + fileList[item].name + "格式不支持!")
}
}
num++;
}
}
//添加一个文件就创建一个file类型的input,只是不显示,用来存储文件
function cereateInput(){
$('.file-content>div').append('<input type="file" name="upload[]" style="z-index:'+ files_num +'" class="add-more"/>');
var addMore = document.querySelectorAll('.add-more')[files_num];
//继续添加文件
addMore.onchange = function(){
if(addMore.files.length > 0){
var fileList = addMore.files;
var num = 0;
addFile(fileList,num);
//添加文件完成后再创建一个input,置于现有的input之上
$('.file-content>div input').addClass('hidden');
files_num++;
console.log(files_num)
cereateInput();
}
//创建预览
createPreview();
allSize();
}
}
})(jQuery)
三、使用ajax方式进行提交
如果使用ajax提交就把form的action去掉,把input—>type=submit改为type=button,通过添加点击事件来触发,
在原有的js代码基础上增加一下代码:
注意:contentType: false和processData: false 是必须要加上的,通过使用ajax提交文件可以检测到文件的上传进度,下面的代码中就是添加了一个进度条的例子。
需要在页面中增加进度条的部分:
<div class="progress-content hidden">
<progress></progress>
<span id="progress">0%</span>
</div>
//上传
$('#submit').on('click', function() {
//点上传时显示进度条
$('.progress-content').removeClass('hidden');
var formData = new FormData($("#uploadForm")[0]);
uploadFile(formData);
})
function uploadFile(Data){
$.ajax({
url : "./upload",
type: "POST",
data: Data,
xhr : function(){ //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ //检查upload属性是否存在
//绑定progress事件的回调函数
myXhr.upload.addEventListener('progress',progressHandlingFunction, false);
}
return myXhr; //xhr对象返回给jQuery使用
},
success: function(result){
console.log(result);
},
contentType: false, //必须false才会自动加上正确的Content-Type
processData: false //必须false才会避开jQuery对 formdata 的默认处理
});
}
//上传进度回调函数:
function progressHandlingFunction(e) {
if (e.lengthComputable) {
$('progress').attr({value : e.loaded, max : e.total}); //更新数据到进度条
var percent = e.loaded/e.total*100;
$('#progress').html(percent.toFixed(2) + "%");
}
}
页面效果如下:支持的文件格式和单个文件大小是可以设置的
可以继续添加文件或者删除文件
点击上传之后会显示进度条
文件上传完成后进入开始的 uploads文件目录下就可以看到刚才上传的文件了。