翻译:File uploads made easy

翻译:File uploads made easy

原作者Darren Beale  翻译者:梨少

译文:每一次我写很多的代码上传文件,用它上传电子邮件附件或是用于上传图片还有一些动态的片段.我总是尝试着写很少的函数来实现,因此我不想再次写一个代码去实现.现在人们可以在Back-end.org 的支持论坛上问我,如何在一个最近的新闻和文章里面增加图片.为了实现它我写了一些脚本我可能会在下一个版本中加入它.为了把这些事情变得更有趣和更加有用.我将会让它变得普通而且可以在不同的文件类型中重复使用.如果你需要这段代码在你喜欢的代码中使用的话,你可以在这儿下载here.

我们开始需要制定一些参量,你允许用户上传的文件的最大值.如果它是一个图片的话,那么你需要它多高多宽.否则的话你可能得到一个1.5MB 的文件,还有一个1024 x 768 Jpeg 图片在你的视野.

<?php
$my_max_file_size   = "102400";     # in bytes 文件大小
$image_max_width   = "300";     # in pixels 文件宽度
$image_max_height   = "300";    # in pixels 文件高度
?> 下一步是确定最终上传的文件将会在你的服务器的哪一个目录,这需要PHP对这个目录具有写的权限.<?php
$the_path = "/usr/local/apache/htdocs/sites/dev/phpbuilder/upload/files";
?> 现在我们列出我们需要的文件类型然后我们可以给一个容易看出来的错误的信息提示在这段脚本的后面.这一段array数组是人们可读文件类型的的值.<?php
$registered_types = array(
    "application/x-gzip-compressed"     => ".tar.gz, .tgz",
    "application/x-zip-compressed"         => ".zip",
    "application/x-tar"            => ".tar",
    "text/plain"                => ".html, .php, .txt, .inc (etc)",
    "image/bmp"                 => ".bmp, .ico",
    "image/gif"                 => ".gif",
    "image/pjpeg"                => ".jpg, .jpeg",
    "image/jpeg"                => ".jpg, .jpeg",
    "application/x-shockwave-flash"     => ".swf",
    "application/msword"            => ".doc",
    "application/vnd.ms-excel"        => ".xls",
    "application/octet-stream"        => ".exe, .fla (etc)"
); /*these are only a few examples, you can add as many as you like这只是一些例子如果你喜欢的话可以增加更多的*/
?>最后我们需要指定你充许用户上传的文件类型.关于这个例子.它是一个我们需要上传的文件,因此我们建立一个ARRAY数组来关联图片的类型<?php
$allowed_types = array("image/bmp","image/gif","image/pjpeg","image/jpeg");
?>一个OO 的开发者可能会这一段脚本都写在一个类里面,然后把每一个函数都写成一个类的方法.就我个人而言,我还是喜欢用基本的函数的方法来实现.我们开始我们需写一个小的表单函数,我可以很多次的调用它而避免了大部分的杂乱无章的事情.你是不是奇怪为什么会有那么多的\n这是因为输出HTML代码而不全部越线.在这一个大型的项目中,当你看资源时这会变得很容易测试你的代码.<?php
function form($error=false) {
global $PHP_SELF,$my_max_file_size;
               if ($error) print $error . "<br><br>";
               print "\n<form ENCTYPE=\"multipart/form-data\"             action=\"" . $PHP_SELF . "\" method=\"post\">";
               print "\n<INPUT TYPE=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"" . $my_max_file_size . "\">";
               print "\n<INPUT TYPE=\"hidden\" name=\"task\" value=\"upload\">";
               print "\n<P>Upload a file";
               print "\n<BR>NOTE: Max file size is " . ($my_max_file_size / 1024) . "KB";
               print "\n<br><INPUT NAME=\"the_file\" TYPE=\"file\" SIZE=\"35\"><br>";
               print "\n<input type=\"submit\" Value=\"Upload\">";
               print "\n</form>";
} # END form
?>
注意<form enctype..> 我们不增加任何东西那么将不会得到上传.我已经设置了参量为假,这是预定义值的很好的方法因此我放了参量在里面,第二个函数检查返回的值是否正确.在PHP4中已经建立了,但是在PHP3中没有.因此我们要写一些围绕PHP版本的申明如果你的版本为PHP4那么你可以删除所有的东西我已经想过很多,它在不同的服务器上没太多的方法,<?php
if (!ereg("^4",phpversion())) {
             function in_array($needle,$haystack) { # we have this function in PHP4, so for you PHP3 people
        for ($i=0; $i < count($haystack); $i++) {
                     if ($haystack[$i] == $needle) {   
                         return true;
                     }
                 }
             }
}

?>
主函数负责检查我们的上传,像文件类型如果它是一个图片,那么检查它的变量是哪些.<?php
function validate_upload($the_file) {
global $my_max_file_size, $image_max_width,
$image_max_height,$allowed_types,$the_file_type,$registered_types;
   
$start_error = "\n<b>Error:</b>\n<ul>";
                 if ($the_file == "none") { # do we even have a file?
            $error .= "\n<li>You did not upload anything!</li>";
                 } else { # check if we are allowed to upload this file_type
   
        if (!in_array($the_file_type,$allowed_types)) {
            $error .= "\n<li>The file that you uploaded was of a ".
                "type that is not allowed, you are only
                         allowed to upload files of the type:\n<ul>";
                     while ($type = current($allowed_types)) {
                $error .= "\n<li>" . $registered_types[$type] . " (" . $type . ")</li>";
                next($allowed_types);
                     }
            $error .= "\n</ul>";
                 }
                     if (ereg("image",$the_file_type) && (in_array($the_file_type,$allowed_types))) {
        
            $size = GetImageSize($the_file);
                     list($foo,$width,$bar,$height) = explode("\"",$size[3]);
   
                     if ($width > $image_max_width) {
                $error .= "\n<li>Your image should be no wider than " .
                    $image_max_width . " Pixels</li>";
                     }
            
                     if ($height > $image_max_height) {   
                $error .= "\n<li>Your image should be no higher than " .
                    $image_max_height . " Pixels</li>";
                     }
        
                 }
                 if ($error) {
            $error = $start_error . $error . "\n</ul>";
                     return $error;
                 } else {
                     return false;
                 }
             }
} # END validate_upload
?>
笔记:1-4我们开始告诉了哪些变得是全局使用,这省去了我们到处用$GLOBALS[] ,5.开始我们的错误信息6-9如果没有文件,$the_file 设置了空我们检查用户是否实际上传了文件13-21 这儿in_array 和两个array 我们很早就让它运行了.我们通过$allowed_types和$the_file_type 这两个数组,如果数组知道它,那么就接受它,如果不是允许的那么$registered_types数组则返回错误信息.23-35:如果上传的文件是一个图片,我们需要检查它的参量小于我们预定义的值.我们利用了PHP 中的getimagesize() 来检查图片的维度,如果它太大了那么将会给出错误字句.37-42:如果我们有任何东西在$error上,我们完成了字符关闭或返回了,或是返回为错误,那么它工作完成.下面函数并不一定真的需要,我指出的是这是用来确认用户的文件已经上传了,.所的循环通过上传目录和打印出文件在里面除了'.'和 '..' <?php
function list_files() {
global $the_path;
    $handle = dir($the_path);
          print "\n<b>Uploaded files:</b><br>";
          while ($file = $handle->read()) {
              if (($file != ".") && ($file != "..")) {
                  print "\n" . $file . "<br>";
                 }
          }
          print "<hr>";
}
?>
最后的函数把我们所有的函数都联系在一起.它把文件放上去然后用validate_upload()它是否被允许.如果我们需要从临时文件目录复制或是移到到一个空闲的地方我们最后必需清楚我们需要复制到的目录.如果这不都是允许的或是一个无效路径.如果一切都OK,那么我们调用list_files() 然后重现表单.<?php
function upload($the_file) {
global $the_path,$the_file_name;
        $error = validate_upload($the_file);
        if ($error) {
        form($error);
        } else { # cool, we can continue
        if (!@copy($the_file, $the_path . "/" . $the_file_name)) {
            form("\n<b>Something barfed, check the path to and ".
            "the permissions for the upload directory</b>");
            } else {
            list_files();
            form();
            }
        }
} # END upload
?>
我们最后的代码将把事情移开.我们用case()的条件申明来选择任务.它可能带来轻度的损失,但是我会让你看到它是如何被应用的.尽管有很多开发人员不同意我的观点,但是它在大型项目中会增加代码可读性如果$task = upload 那么上传就会开始,否则的话就会出现默认的表单.<?php
print "<html>\n<head>\n<title>Upload example</title>\n</head>\n<body>";
switch($task) {
        case 'upload':
        upload($the_file);
        break;
        default:
        form();
}
print "\n</body>\n</html>";
?>
这样,运行这些脚本用户能看到一个上传的区域,他们可以浏览硬盘中的文件和点击按钮.如果在验证过程没有错误的话,那么他们将会得到一个返回的上传目录列表而且表单会再出现,他们可以上传其它的文件.-- Bealers 很好理解,我没有增加对于max_file_size(文件大小)错误的检查机制在关闭错误报告时,AFAIK是唯一完美捕获错误的方法而且代码运行是基于检查机制的,然而,我喜欢在开发过程中看到错误,我猜想,我们太相信PHP错误所以被欺骗了.这个例子不是要告诉你在上传图片时应该做些什么.举个例来说吧,当我发布Back-end的下一个版本时,你可能允许用户在文章中上传图片.通过这个例子,你可能在页面被浏览后为文章增加文件名.PHP可以指出对应的图片.我将会让你指出它./**************************************************备注;原文出处:http://phpbuilder.com/columns/bealers20000904.php3?page=1MY BLOG; http://hi.baidu.com/hrxn/这篇文章是我翻译的第一篇文章,由于时间和水平有限,难免会有一些翻译上的错误.望大家多多见谅.这文件是我昨天在PHPBUILDER 上看到的,我觉得不错便觉得应该把它翻译成中文.昨天用了四十多分钟翻译了大部分内容,但是后事停电了,不得不今天中午才完成后面的收尾.这个月初支身一人从云南来到了南昌求学,初到南昌一切不是很熟悉,有江西的朋友吗?可以加我的QQ 490821193 或是发短信给我大家一起探讨一下.15879051373由于本人非计算机专业,所以有些专业词汇翻译上可能有出入,再次请大家见谅.*/

好长呀
只有拼搏,努力和进取,自己的未来才会更美好