1. 前言
实现多文件上传这个功能,已经是后台开发中很常见的需求了。当前主流的前端框架都提供了直接的上传控件,如vue-upload-component、iview中的upload等,它们使前端开发人员实现上传功能变得轻松便捷。但当我们需要自行实现上传功能时,不同的后台语言具有不同的处理方式。这篇文章将介绍如何使用layui+php实现多文件上传这一功能。
2. 项目结构
首先,创建项目文件夹,文件夹下分别创建“index.html”、“upload.php”和“layui”文件夹,如下所示:
- 项目文件夹
|__ index.html
|__ upload.php
|__ layui/
其中,“index.html”文件用于前端页面,我们需要使用layui库中的组件来实现上传功能;“upload.php”文件用于接收前端传递的数据和上传的文件,并实现上传到指定目录中的功能;“layui”文件夹用于存放layui库中的静态资源(js、css)。
3. 前端页面
3.1 页面结构
我们使用layui中的upload组件来实现上传功能。首先在“index.html”中添加如下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layui+php实现多文件上传</title>
<link rel="stylesheet" href="./layui/css/layui.css">
</head>
<body>
<div class="layui-upload">
<button type="button" class="layui-btn layui-btn-normal" id="testList">上传图片</button>
<div class="layui-upload-list">
<table class="layui-table">
<thead>
<tr>
<th>文件名</th>
<th>大小</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="demoList">
</tbody>
</table>
</div>
</div>
<script src="./layui/layui.js"></script>
<script>
//JavaScript代码块
</script>
</body>
</html>
整个页面结构中有一个div,使用了layui-upload组件和layui-table组件,其中upload组件用于渲染上传按钮,table组件用于渲染上传后的文件列表。我们需要在JavaScript中实现关于upload组件的操作。在页面结构后,需要通过script标签来引入layui库和自定义JavaScript代码,如上所示。
3.2 JavaScript代码块
接下来,我们在[xss_clean]标签中,实现JavaScript代码块,达到操作upload组件和文件列表的目的。初次接触Layui的开发者需要注意三个比较重要的概念:模块、元素操作、事件监听。首先我们预先定义好上传组件的实例,然后监听“选择图片”和“开始上传”两个事件,使用ajax上传文件,并将选中的文件信息添加到“demoList”文件列表中。代码如下:
layui.use(['upload', 'layer'], function(){
var $ = layui.jquery,
upload = layui.upload,
layer = layui.layer;
//多文件列表示例
var demoListView = $('#demoList'),
uploadListIns = upload.render({
elem: '#testList',
url: 'upload.php',
accept: 'file',
multiple: true,
auto: false,
bindAction: '#testListAction',
choose: function(obj){
//预读本地文件,如果是多文件,则会遍历。(不支持ie8/9)
obj.preview(function(index, file, result){
var tr = $(['<tr id="upload-'+ index +'>',
'<td></td>',
'<td></td>',
'<td>等待上传</td>',
'<td>',
'<button class="layui-btn layui-btn-xs layui-btn-danger demo-delete">删除</button>',
'</td>',
'</tr>'].join(''));
//单个重传
tr.find('.demo-reload').on('click', function(){
obj.upload(index, file);
});
//删除
tr.find('.demo-delete').on('click', function(){
delete files[index]; //删除对应的文件
tr.remove();
uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除后出现同名文件不可选
});
demoListView.append(tr);
$('tr#upload-'+index).find('td').eq(0).text(file.name);
$('tr#upload-'+index).find('td').eq(1).text((file.size/1024).toFixed(1)+'KB');
});
},
done: function(res, index, upload){
if(res.code == 0){ //上传成功返回值
$('tr#upload-'+index).find('td').eq(2).text('上传成功');
$('tr#upload-'+index).find('td').eq(3).html('<a href="' + res.data.src + '" target="_blank">' +
'<img src="' + res.data.src + '" class="layui-upload-img"></a>');
}else{
$('tr#upload-'+index).find('td').eq(2).text('上传失败');
$('tr#upload-'+index).find('td').eq(3).find('.layui-progress-bar').css('width', '0%');
}
},
error: function(index, upload){
$('tr#upload-'+index).find('td').eq(2).text('上传失败');
$('tr#upload-'+index).find('td').eq(3).find('.layui-progress-bar').css('width', '0%');
}
});
});
上传组件操作代码的详细解释已添加在代码注释中。上述代码实现了多文件上传和删除功能,它会在上传完毕后将上传成功的文件的路径返回给前端页面,以实现查看上传的图片功能。同时,需要创建文件夹“uploads”,用于存放上传的图片文件。最终,“index.html”文件结构大致为:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>layui+php实现多文件上传</title>
<link rel="stylesheet" href="./layui/css/layui.css">
</head>
<body>
<div class="layui-upload">
<button type="button" class="layui-btn layui-btn-normal" id="testList">上传图片</button>
<div class="layui-upload-list">
<table class="layui-table">
<thead>
<tr>
<th>文件名</th>
<th>大小</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="demoList">
</tbody>
</table>
</div>
</div>
<script src="./layui/layui.js"></script>
<script>
layui.use(['upload', 'layer'], function(){
var $ = layui.jquery,
upload = layui.upload,
layer = layui.layer;
//多文件列表示例
var demoListView = $('#demoList'),
uploadListIns = upload.render({
elem: '#testList',
url: 'upload.php',
accept: 'file',
multiple: true,
auto: false,
bindAction: '#testListAction',
choose: function(obj){
//预读本地文件,如果是多文件,则会遍历。(不支持ie8/9)
obj.preview(function(index, file, result){
var tr = $(['<tr id="upload-'+ index +'>',
'<td></td>',
'<td></td>',
'<td>等待上传</td>',
'<td>',
'<button class="layui-btn layui-btn-xs layui-btn-danger demo-delete">删除</button>',
'</td>',
'</tr>'].join(''));
//删除
tr.find('.demo-delete').on('click', function(){
delete files[index]; //删除对应的文件
tr.remove();
uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除后出现同名文件不可选
});
demoListView.append(tr);
$('tr#upload-'+index).find('td').eq(0).text(file.name);
$('tr#upload-'+index).find('td').eq(1).text((file.size/1024).toFixed(1)+'KB');
});
},
done: function(res, index, upload){
if(res.code == 0){ //上传成功返回值
$('tr#upload-'+index).find('td').eq(2).text('上传成功');
$('tr#upload-'+index).find('td').eq(3).html('<a href="' + res.data.src + '" target="_blank">' +
'<img src="' + res.data.src + '" class="layui-upload-img"></a>');
}else{
$('tr#upload-'+index).find('td').eq(2).text('上传失败');
$('tr#upload-'+index).find('td').eq(3).find('.layui-progress-bar').css('width', '0%');
}
},
error: function(index, upload){
$('tr#upload-'+index).find('td').eq(2).text('上传失败');
$('tr#upload-'+index).find('td').eq(3).find('.layui-progress-bar').css('width', '0%');
}
});
});
</script>
</body>
</html>
4. 后台部分(upload.php)
4.1 PHP代码块
接下来我们来处理服务器端的代码。在“upload.php”文件中,使用PHP语言处理上传文件的逻辑,并将上传的文件保存到指定目录中。代码如下所示:
<?php
header("Content-Type:text/html;charset=utf-8");
$file = $_FILES['file'];
//文件存储路径
$save_path = dirname(__FILE__) . '/uploads/';
if(!file_exists($save_path)){
mkdir($save_path, 0777, true);
}
$save_name = uniqid() .'.png';
if(move_uploaded_file($file['tmp_name'], $save_path . $save_name)){
$res_arr = array('code' => 0, 'msg' => '', 'data' => array(
'src' => $save_path . $save_name
));
echo json_encode($res_arr);
}
else{
echo '文件上传失败,请重试。';
}
?>
在PHP代码块中,首先将接收到的文件与要上传的路径存储下来,判断要上传的文件存储路径是否存在,如果不存在则创建一个权限为0777的文件夹。然后,通过图片上传时生成的临时文件名和路径,将文件移动到要上传的文件目录下。最后,将上传成功的文件的路径返回给前端页面。需要注意的是,在上传实例化中定义的是url: 'upload.php',这里的url也需要保存一致。
4.2 前置条件
上述php代码中,使用了dirname(__FILE__),该命令在Windows系统中会报错。需要修改php.ini文件中的doc_root为自己的工作目录,或将dirname(__FILE__)修改为__DIR__。
5. 总结
本文主要介绍了如何使用layui+php实现多文件上传功能,上传按钮使用了layui中的upload组件,上传后的文件列表使用了layui中的table组件。在这个过程中,需要注意Layui中的JavaScript操作方式,以及PHP中的文件上传原理,也需要注意php代码的一些前置条件。希望通过本文的介绍,能够帮助更多的读者轻松实现多文件的上传功能。