首页编程PHP典型模块上传与下载模块文章详细

PHP实现文件上传的原理。

原创 2023-09-17 21:28:20 210

上传和下载是互联网上最常见的服务,该服务不仅方便了用户的使用,同时也丰富了网站资源。通过文件的上传和下载功能,可以使资源更好地共享,使网站成为真正的开放平台。上传部分和下载部分的原理有很大的不同,本章将从上传和下载的原理讲起,由浅入深地展开,最终将上传功能与下载功能整合成一个完整的应用平台。

本章主要涉及的知识点有:

PHP实现文件上传的原理。

PHP防盗链的程序实现原理。

JavaScript文件尺寸判断核心ActiveXObject0控件。

在PHP中使用header)函数向浏览器发送原始HTTP标头。


在B/S结构的程序开发中,文件上传的原理都是相同的。本节将讲解基于PHP的文件上传原理并实现编码。文件下载部分原理并不复杂,但是如果直接开放链接给用户下载就会造成很多的问题,所以提供基于防盗链的下载链接十分必要,通过防盗链可以更好地保护网站资源。

1.PHP文件上传的原理及实现

PHP中,文件上传功能是使用PHP提供的文件函数来实现的。下面通过例子使读者直观地了解上传的原理以及程序编码的实现。

1.客户端上传

创建一个文件upload.html,这是一个最基本的上传的表单代码,代码如下:

<html xmlns="undefined">
<head>
<title>文件上传页面</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="description" content="文件上传页面" />
<style type="text/css">
body,td{font-family:tahoma,verdana,arial;font-size:11px;line-height:15px;background-color:white;color:#666666;
strong{font-size:12px;}
a:link{color:#0066CC;}
a:hover{color:#FF6600;}
a:visited{color:#003366;}
a:active{color:#9DCC00;}
a{TEXT-DECORATION:none}
td.irows{height:20px;background:url("index.php?i=dots") repeat-x bottom}
</style>
</head>
<body bgcolor="#FFFFFF">
<center>
  <form enctype="multipart/form-data" action="" method="post"> 
    <table border="1" width="55%" id="table1" cellspacing=0>
      <tr>
        <td colspan="2">
            <p align="center">上传文件:
        </td>
      </tr>
      <tr>
        <td width="10%">

        </td>
        <td width="71%">
            <input type="hidden" name="max_file_size" value="100000">
            <input name="userfile" type="file"> 
            <input type="submit" value="上传文件">
        </td>
      </tr>
    </table>
    允许上传的文件类型为:jpg|jpeg|gif|bmp|png|swf|mp3|wma|zip|rar|doc
 </form>
</center>
</body>
</html>

在浏览器中加载upload.html文件,效果如图7.1所示。

upload.png

图7.1 文件上传表单预览

要实现文件的上传,需要在表单标签中设置以下选项,以确保匿名上传文件的正确编码。

enctype="multipart/form-data"

【代码解读】

表单选项MAX_FILE_SIZE的隐藏值域,通过设置Value值的大小可以限制上传文件的尺寸。当然,MAX_FILE_SIZE的值相对于浏览器只是一个参考值,实际上它可以被轻易地绕过。实际应用中是通过在PHP配置文件中设置上传文件最大值,来做上传文件的限制的。在表单中加上MAX_FILE_SIZE,可以及时发现上传文件尺寸过大的问题。

2.服务器端上传

创建服务器端上传处理文件upload.php,代码如下:

<?php
    $file=$_FILES['userfile'];  //接收表单信息
    $dest_dir = 'up';                    //设定上传目录
    $dest = $dest_dir . time() . $file['name'];  //设置文件名为时间加文件名,这样可有效避免重读
    if(!$file){
        echo "<font color='red'>移动文件出错!</a>";
        exit;
    }else{
        $r = move_uploaded_file($file['tmp_name'],$dest);
        //chmod($dest,0755);    //设定上传的文件属性
        echo "<font color='red'>恭喜文件". $dest ."上传成功</a>";
    }
?>

【代码解读】

当文件上传成功后,系统会提示文件上传成功的信息。上面例子中$_FILES['userfile']数组的内容含义如下所示。

$_FILES['userfile']['name']:客户端机器文件的原名称。

$_FILES['userfile']['type']:文件的MIME类型,例如“image/gif”。

$_FILES['userfile']['size']:已上传文件的大小,单位为B

$_FILES[userfile']['tmp_name']:文件被上传后在服务端储存的临时文件名。

$_FILES[userfile']['error']:该文件上传相关的错误代码。

其中,错误代码的含义如下所示。

值0:没有错误发生,文件上传成功。

值1:上传的文件超过了php.iniupload_max_filesize选项限制的值。

值2:上传文件的大小超过了HTML表单中MAX_FILE_SIZE选项指定的值。

值3:文件只有部分被上传。

值4:没有文件被上传。

2.PHP文件下载的原理及实现

通常文件下载过程是十分简单的,建立一个链接指向到目标文件就可以了。例如下面的链接:

<a href="http://www.xxx.com/xxx.rar">点击下载文件</a>

但是,实际情况可能会稍复杂。比如需要用户填写完整注册信息后才可以下载该文件,这时最先想到的是使用Redirect的方式。下面介绍两种方式。

(1)用Redirect方式。先检查表格是否已经填写完毕和完整,然后将链接指到该文件,这样用户就可以下载。请看下面的示例代码:

<?php
    /*文件功能:检查变量form是否完整*/
    if($form){
    //重新定向浏览器指向
    Header("Location: http:// http://www.xxx.com/xxx.rar");
        exit;
    }
?>

(2)根据下载文件的序号来查找,链接的形式如下:

<a href="http://www.xxx.com/download.php?id=123456">点击下载文件</a>

上面的链接使用ID方式接收要下载文件的编号,然后再用Redirect的方式连接到真实的文件链接。

以上这两种方法虽然实现了文件的下载功能,但是缺点是直接暴露了文件所属的路径,而且没有防盗链的功能,所以上面的方式是简单直接但存在安全隐患的文件下载方式。在PHP中,通常是利用header()函数和fread()函数来实现安全的文件下载。

例如,需要下载的是一个文件名为xxx.rar的文件,首先创建文件是download.phpPHP文件。通过前面的例子很容易通过文件的ID号从数据库中得到待下载文件的真实位置,在获得文件的真实存储位置后,可以通过header()函数的location参数直接重定向到这个文件。但是这样仍然是不安全的,因为某些下载软件还是可以通过重定向分析获得该文件的位置信息。因此需要用另外一种方法,就是PHP的文件处理API函数。它是通过fread()函数把文件直接输出到浏览器提示用户下载,这样所有的处理都是在服务器端完成的,因此用户就无法获得文件具体存储位置信息的,示例代码如下:

<?
$file_name = "xxx.rar";     //下载文件名
$file_dir = "./up/";        //下载文件存放目录
//检查文件是否存在
if (!file_exists($file_dir . $file_name)) { 
    echo“文件找不到”;
    exit();
}else{
    // 打开文件
    $file = fopen($file_dir . $file_name,"r");  
    // 输入文件标签 
    Header("Content-type: application/octet-stream"); 
    Header("Accept-Ranges: bytes"); 
    Header("Accept-Length: ".filesize($file_dir . $file_name)); 
    Header("Content-Disposition: attachment; filename=" . $file_name); 
    // 输出文件内容 
    //读取文件内容并直接输出到浏览器
    echo fread($file,filesize($file_dir . $file_name)); 
    fclose($file); 
    exit;
}
?>

【代码解读】

上述代码中,程序发送Header信息是用来告诉Apache和浏览器下载文件的相关信息的。content-type的含义代表文件MIME类型是文件流格式。如果在Apache配置里面把文


件的MIME类型设为application/octet-stream(如add application/octet-stream.xxx.rar),那么浏览器(客户端)就会知道,这是一个文件流格式的文件并提示用户下载。Accept-Ranges是一个响应头标,它允许服务器指明将在给定的偏移和长度处,为资源组成部分的接受请求,该头标的值被理解为请求范围的度量单位。Content-Length 是指定包含于请求或响应中数据的字节长度,例如,Content-Length:382Content-Disposition:attachment是用来告诉浏览器,文件是可以当做附件被下载,下载后的文件名称为$file_name该变量的值。

运行download.php文件,效果如图7.2所示。从图中可以看到文件按照预想的方式被提示下载,单击“保存”按钮将文件保存在本地。

xxx.png

图7.2 PHP文件安全下载

推荐