题目中的上传包含两部分,一部分是上传文件,一部分是利用PHP执行脚本
上传文件到指定文件夹
所谓文件上传是指将本地文本文件,图片视频或者音频等文件上传到服务器上,以供后续操作的过程。
上传文件有几种方式,包括:
- 单纯的form表单上传提交
使用form表单的input[type=”file”]控件,打开系统的文件对话选择框,选择文件然后利用submit和form中跳转的action设置实现上传。
优点:多浏览器兼容,简单
缺点:PHP会限制浏览器上传文件的大小,而且form表单提交后会刷新页面,用户体验不好
【注意】
1. input中type要设置成type=”file”;
2. 设置form中method=”post”;
3. form中enctype中有三种取值
如果是文件上传,需要将enctype=”multipart/form-data”
如果上传文件较大,需要配置php.ini文件(以上传500M以下大小的文件为例)
查找以下选项并修改->
file_uploads = On ;打开文件上传选项
upload_max_filesize = 500M ;上传文件上限
如果要上传比较大的文件,仅仅以上两条还不够,必须把服务器缓存上限调大,把脚本最大执行时间变长
post_max_size = 500M ;post上限
max_execution_time = 1800 ; Maximum execution time of each script, in seconds脚本最大执行时间
max_input_time = 1800 ; Maximum amount of time each script may spend parsing request data
memory_limit = 128M ; Maximum amount of memory a script may consume (128MB)内存上限
上代码:
<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<input type="file" name="file" id="file" />
<input type="submit" name="submit" id="submit" value="Submit" />
</form>
效果如图:
原始的样子不太好看,为了美观大家可以使用label调整样式,例如
css部分
.btn {
display: inline-block;
margin-bottom: 0;
user-select: none;
}
.btn-info {
padding:8px;
color: #ffffff;
background-color: #40bbea;
border-color: #29b3e7;
}
html部分
<div>
<label for="fileName1" >文件上传:</label>
<input type="text" name="fileName1" id="fileName1" style="height: 32px;width: 300px;" />
<label class="btn btn-info" for="updateFile" style="margin-bottom: 3px;">浏览</label>
<label class="btn btn-info" style="margin-bottom: 3px;" for="submit" >上传</label>
<div class="col-xs-12">
<form id= "uploadForm">
<input type="file" id="updateFile" name="file" style="position:absolute;clip:rect(0 0 0 0);">
<input type="text" id="submit" hidden="hidden">
</form>
</div>
</div>
修改后样式如图:
-html5的formdata、fileReader
利用FormData模拟表单数据,然后通过ajax提交,用FileReader的readAsDataURL方法拿到base64地址来预览。
html部分
<div id= "uploadForm">
<input type="text" id="fileName" style="height: 32px;width: 300px;" />
<label class="btn btn-info" for="file" style="margin-bottom: 3px;">
<span>浏览</span>
</label>
<label class="btn btn-info" style="margin-bottom: 3px;" for="submit">
<span>上传</span>
</label>
<input type="file" id="file" name="file" onchange="showPreview(this)" style="position:absolute;clip:rect(0 0 0 0);">
<input type="text" id="submit" onclick="doUpload()" hidden="hidden">
</div>
JavaScript部分
function showPreview(source) {
var arrs = $(source).val().split('\\');
var filename=arrs[arrs.length-1];
$("#fileName").val(filename);
}
function doUpload() {
var formData = new FormData($( "#uploadForm" )[0]); // 要求使用的html对象
$.ajax({
url: 'upload_file.php' ,
type: 'POST',
data: formData,
async: true,
// 下面三个参数要指定,如果不指定,会报一个JQuery的错误
cache: false,
contentType: false, //不要设置Content-Type请求头,因为文件数据是以 multipart/form-data 来编码
processData: false,//不处理数据
success: function (returndata) {
/*result = JSON.parse(returndata);*/
alert(returndata);
},
error: function (returndata) {
alert(returndata);
}
});
}
需要注意的部分:
使用jQuery提供的ajax方法来发送二进制文件,还需要附加两个参数:
processData: false // 不要对data参数进行序列化处理,默认为true
contentType: false // 不要设置Content-Type请求头,因为文件数据是以 multipart/form-data 来编码
upload_file.php
<?php
$url=realpath(dirname(__FILE__).'/../../'); //从当前位置退回到www文件夹目录,这一块儿可根据自己文件所在位置做修改
if ($_FILES["file"]["error"] > 0)
{
switch($_FILES["file"]["error"])
{
case 1:
echo "上传文件的大小超出了约定值";
break;
case 2:
echo "上传文件太大 ";
break;
case 3:
echo "文件只被部分上传";
break;
case 4:
echo "没有上传任何文件";
break;
case 6:
echo "未指定临时目录";
break;
case 7:
echo "文件写入磁盘失败" ;
break;
}
}
else
{
$storePath = $url. "/upload" ;
// 判断当期目录下的 upload 目录是否存在该文件
// 如果没有 upload 目录,你需要创建它,upload 目录权限为 777
if (!file_exists($storePath))
{
mkdir($storePath);
}
else if (file_exists($storePath.'/'.$fileName))
{
echo $fileName . " 文件已经存在,如需更新,请点击下方'更新系统'按钮";
}
else
{
//如果 upload 目录不存在该文件则将文件上传到 upload 目录下
//判断文件上传是否采用的POST方式
if(is_uploaded_file($_FILES['file']['tmp_name']))
{
if(move_uploaded_file($_FILES['file']['tmp_name'],$storePath.'/'.$fileName))
{
chmod($storePath.'/'.$fileName,0755);//
echo "更新文件存储成功,如需更新,请点击下方'更新系统'按钮";
}else{
echo '更新文件存储失败';
}
}else{
echo '没有可存储的更新文件';
}
}
}
?>
关于PHP上传文件
通过使用 PHP 的全局数组 $_FILES,你可以从客户计算机向远程服务器上传文件。
第一个参数是表单的 input name,第二个下标可以是 “name”, “type”, “size”, “tmp_name” 或 “error”。就像这样:
_FILES[“file”][“type”] - 被上传文件的类型
_FILES[“file”][“tmp_name”] - 存储在服务器的文件的临时副本的名称
$_FILES[“file”][“error”] - 由文件上传导致的错误代码
这是一种非常简单文件上传方式。基于安全方面的考虑,您应当增加有关什么用户有权上传文件的限制,例如上传格式和大小。
保存上传的文件到指定文件夹
使用move_uploaded_file(
storePath.’/’.
storePath.'/'.$fileName,0755);这个是为了修改上传文件的权限,因为上传文件的权限默认是644,所以如果有执行该文件的需求则需要自己手动修改权限;
而标题的第二部分是利用php执行linux命令,shell脚本函数
PHP执行外部命令的几个函数
- exec()
string exec ( string command [, array &output [, int &return_var]] )
说明:
前面是要执行的命令,但是exec执行系统外部命令时不会输出结果,而是返回结果的最后一行。如果想得到结果,可以使用第二个参数,让其输出到指定的数组。此数组一个记录代表输出的一行。即如果输出结果有20行,则这个数组就有20条记录,所以如果需要反复输出调用不同系统外部命令的结果,最好在输出每一条系统外部命令结果时清空这个数组unset($output),以防混乱。第三个参数用来取得命令执行的状态码,通常执行成功都是返回0 - shell_exec()
string shell_exec ( string cm,输出命令执行结果,如果执行过程中发生错误或者进程不产生输出,则返回 NULL,所以,使用本函数无法通过返回值检测进程是否成功执行。 - system()
string system ( string return_var ] )
说明:system和exec的区别在于,system在执行系统外部命令时,它执行给定的命令,输出和返回结果。第二个参数是可选的,用来得到命令执行后的状态码。
状态码介绍
如果返回0是运行成功,
在Bash中,当错误发生在致命信号时,bash会返回128+signal number做为返回值。
如果找不到命令,将会返回127。
如果命令找到了,但该命令是不可执行的,将返回126。
除此以外,Bash本身会返回最後一个指令的返回值。
若是执行中发生错误,将会返回一个非零的值。
Fatal Signal : 128 + signo
Can’t not find command : 127
Can’t not execute : 126
Shell script successfully executed : return the last command exit status
Fatal during execution : return non-zero - passthru()
void passthru ( string return_var ] )
说明: passthru与system的区别,passthru直接将结果输出到浏览器,不返回任何值,且其可以输出二进制,比如图像数据。第二个参数可选,是状态码。
当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system() 函数。 常用来执行诸如 pbmplus 之类的可以直接输出图像流的命令。 通过设置 Content-type 为 image/gif, 然后调用 pbmplus 程序输出 gif 文件, 就可以从 PHP 脚本中直接输出图像到浏览器。