PHP | 小白建站笔记之 文件上传(易忽略的关键点)

文件的下载很简单,在前端HTML标记语言中就能实现。但是,文件的上传却不是那么容易,需要进行服务器端的简单编程。而且,还有很多细节方面的注意事项,官方文件中都没有说明,这也是很多人对文件上传这个问题很苦恼的原因。其实只需要注意几个细节,就能轻松搞定文件上传啦!

图文 / 丁建雄

小白是单纯为兴趣而写作的独立创作人,如果您喜欢小白的文章,欢迎关注、交流、分享(引用请链接到本文)。

每一点细小的努力都值得被尊重 By [Andre Villeneuve](https://500px.com/andre_villeneuve)

PHP简介

PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。

这个是百度百科的解释,其实简单来讲,PHP就是一门在服务器端通用的编程语言,功能十分强大!

HTML是一种标记语言,而对于一些需要复杂动态运算的算法设计,HTML就无法实现了。这个时候,在服务器端,就需要类似PHP,JavaScript这种脚本语言来实现。小白的背景是光电专业,当时学的是C++,所以对PHP这种通用型脚本语言情有独钟。

PHP是一种比较松散的语言,这也就使得他更接近于人类自然语言,没有很多的限制,但是你需要注意更多的细节,才能游刃有余,小白强烈推荐!

文件上传

这里所指的文件上传不同于服务器端的FTP上传,是指在网页客户端,在访问页面进行实时的文件上传操作。

具体而言,实现方法有很多种,比如:基于Java、xml、HTML的方法;在HTML页面直接嵌入式简单JavaScript的方法;使用Apache fileupload库的方法;基于HTML、PHP脚本的方法等。

小白基本这些方法都尝试过,个人觉得HTML+PHP的方法最稳定、简单、实用。

HTML表单

HTML表单是一个强大的网页信息交互系统,尤其是一些少量信息的交互,表单处理将变得十分高效。

大家可以这么理解,我们浏览网页大部分时候只是为了得到信息。但是有些时候,我们需要向网页反馈我们的想法、信息,这个时候就需要表单出场了。

至于表单的细节性问题,这里先不细聊,在我的前端开发文章集 [ 网页设计 ] 篇章会有文章专门讨论表单,这里就直截了当上代码。

<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Hello, world</title>

    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">

  </head>
  <body>
    <h1>你好,世界!</h1>

    <!--put your contents here-->

    <form action="upload.php" method="post" enctype="multipart/form-data">
        <label for="file">Filename:</label>
        <br/>
        <br/>
        <input type="file" name="file" id="file"/> 
        <br />
        <input type="submit" name="submit" value="提交上传" />
    </form>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
  </body>
</html>

这里代码还是沿用的之前Hello,World的版本,注意中间 <form></form> 部分是新增的代码。

稍微解释一下各个部分的内容:

action="upload.php" 是页面指向,也就是这个表单提交的页面URL是 upload.php ,这个页面其实是我们下面要编写的一个处理脚本程序。程序是需要变量的,而下面的 input 选项就是存放的变量,包含了变量的类型 type和变量的名称 name

我们是制作一个上传文件的表单,那么表单的方法就是上传,即 method="post" 。我们还要指定文件的编码方式,默认地,表单数据会编码为 application/x-www-form-urlencoded 。就是说,在发送到服务器之前,所有字符都会进行编码,这是单纯的文字的编码方式。但是,对于文件就不行了,得使用 multipart/form-data 方法。

那个 <label> 是等同于输入文件按钮的一个新的标签,也就是说你可以在同一个页面的不同处设立上传按钮,上传到同一个空间,而只需要重写标签,不需要重写上传控件。

<input type="file" name="file" id="file"/> 定义了上传控件文件的类型、名称、和ID(为了重定义标签使用的名字)。

<input type="submit" name="submit" value="提交上传" /> 这个是提交按钮,只要点了这个按钮,就会转向脚本文件,并把文件上传到服务器上。

其实,表单属性如果要细聊会很复杂。当然,也正是由于他的重要性,多样性,才有了多姿多彩的网页设计规划。这是一个非常有趣的话题,小白将在前端的文章中跟大家好好讨论一下。

PHP脚本

PHP语言的一般结构

<?php
echo "Hello,World!";
?>

是不是很简单,这个就是PHP版本的Hello,world。

其实,PHP还可以跟HTML语言混合使用,基本上HTML能做的事情,PHP都能做到,就是可能在繁琐程度上会有不同。而且,类似上面的Hello,World在PHP编写好之后,是可以直接发布到HTML上显示的,只需要额外套用个HTML框架即可,比如

<!DOCTYPE html>
<html>
<body>

<?php
echo "Hello,World!";
?>

</body>
</html>

就跟之前的网页版Hello,world的显示效果几乎一模一样(这里为了大家能看清楚,没有套用之前Bootstrap的框架)。

代码部分,我这边是参考的w3school的 PHP教程,自己稍微做了一些修改

<?php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 2000000))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>

这个就是表单中提到的 upload.php 文件了。

这边一些基本的条件语句相信大家有点编程基础的都能看懂吧,这边就不赘述了。

PHP变量命名规则是以 $ 开始的,这里的变量其实就一个 $_FILES。注意,PHP变量是对大小写敏感的。其余的变量属性 file name type size 等都是从表单中获得的,也就是说,这个脚本的实例化是依赖于表单的输入文件的。这个PHP文件只是作为一种处理方法,而跟HTML标记不一样,不具有实际存在的形态,必须依赖于外部输入才能执行。

这里,前面三个 和一个 条件构成了上传文件的约束 。在这里,规定只能上传 gif、jpeg 、和 pjpeg 格式的小于2000000bit大小的图片。当然,这个只是个约束范例,如果大家要传输各类文件,只需要加上其他约束就行了。如果要任何文件都传输,那么就直接删掉约束条件就行了。但是,不建议这么做,当网站面向大众的时候,这么做很容易成为黑客入侵的快速入口,对服务器来讲是致命的。

内部,关键性的上传代码是

if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }

这条语句的意思是,先看目录下有没有同名称文件,如果有,就提示已经存在相同文件,并提示,且不会继续上传;如果没有相同文件,则使用 move_uploaded_file 方法将文件上传到指定目录中,并且输出存储目录。

这里,最关键的上传步骤就存在于上传方法那个封装好的函数之中,这块是标准化的库函数,大家直接调用就可以了,在安装了PHP的服务器上,这个函数是存在于默认的库中的,不需要额外添加。

分享一个自己的小故事

关键词:权限、刷新——服务器文件默认权限对文件上传的影响。

一般来讲,服务器为了安全性考虑,一般是默认只读权限。小白使用的CentOS系统,安装的是Apache服务器。

这里还有个小故事,小白初次接触文件上传的时候,在网上找了各路博客大神的帖子,基本把相关的热帖都看遍了,还有官方说明文档。但是,很不巧,文件上传总是不成功(虽然文件提示都已经上传了,也就是说程序都跑通了,但是服务器上就是没有文件)。

咋办呢?小白开始怀疑了,难道官方文档也有错?

后来,在折腾了3个小时之后,在一个论坛回复里面看到有人稍微说了一下权限 问题,我也没抱太大希望,因为没多少人讨论过权限。

于是,小白就抱着试试看的心态,修改了目标文件夹的权限。没想到,奇迹出现了—— 提示有变化了,之前都是简单提示已经 存储完毕,这次是 文件已存在

有点小欣喜,但是,目标文件夹还是没有文件啊!

咋办呢?这次至少知道文件已经存储在服务器上了,但是为什么还是看不到呢?难道是延迟?

小白先登出服务器,再进入,还是看不到!到底是个咋回事?当时都已经凌晨3点了,小白真的要崩溃了,但是不搞出来也睡不着啊,算了,撸起袖子继续找,一定要搞出来,毕竟有眉目了!

小白在自己本地的电脑上是习惯于不断刷新(虽然感觉并没有什么用),由于服务器端小白是FTP登录,窗口比较小,没注意过刷新。但是,就在这个时候,小白不小心点了一下刷新!

奇迹出现了,上传的所有文件都出现了!瞬间如释重负、欣喜若狂啊!

哎呀妈呀!原来是这个问题啊,这下我终于懂得刷新的重要性了,瞬间对刷新有了全新的理解!

故事还没结束。

第二天早上,虽然四点多才睡觉的,但是小白8点就醒了,想想昨晚的成果,瞬间又有了动力,继续干,再摸索摸索,看看有没有新的发现。

我把之前的文件夹删除了,新建了一个文件夹,看看上传效果。不搞不知道,一搞吓一跳,原封不动的代码,又不行了!

不过,不要急,这个bug处理过,不就是权限 问题嘛!我把权限修改好,又做了一次,这下好了!这里小白要着重说明一个事情:

很多人都知道设定一个文件夹及其子文件夹的权限之后,原有文件夹的属性肯定是不变的。但是,如果在文件夹下面新建一个子文件夹,那这个子文件夹的权限会继承 父文件夹的权限吗?

答案是,不会!新建的子文件夹权限还是默认的权限,不会因为父辈的权限而继承,若要继承,得再设定一次权限,才能改变新建文件夹的权限属性。

这个问题是最重要的了,小白为这个问题付出了4个多小时的努力,问题虽小,却很关键!

由此,小白感觉现在的各路博客大神 写文章真是有点水了。都喜欢各种转载、抄袭,而不去真正实践,实践才能找到问题,也才能写出真正对求知者有用的文章。否则,泥沙俱下,人云亦云,垃圾太多的结果就是浪费了大家太多的时间。

这也是小白最初想写一点自己的心得的原因。小白每一次的写作都是自己亲自尝试过的,有任何的细小的问题,小白都会在文章中跟大家详细讨论。无惧简单,避免含糊、装高大上。写出最浅显易懂的文章,阐释最基本的技术原理,这是小白的追求。

结语

好啦,又到了本期问题思考环节了!

本期的问题是这样的

问题1:

仔细看的小伙伴一定已经发现了,这个上传重复文件的判断语句似乎是不合理的!

我们正常的文件上传情况都是如果有重复文件,会跳出一个处理对话框,选择是否覆盖掉原始文件,然而这里却没有。你能不能设计一个简单的方案,来弥补这个小缺陷,达到正常的处理效果呢?

问题2:

在服务器端,如果某个文件夹有 权限,会对服务器安全造成影响,具体影响可能有哪些?你有没有什么好的解决办法呢?

技术问题没有高级与低级之分,无论多么细小的问题,你提出来都会给别人或多或少提供帮助与参考。

所以,大家有任何疑问或者建议都可以留言或者私信小白哦~

欢迎各位查阅相关资料,在留言中积极参加讨论。

参考文献
PHP_百度百科
HTML_<form>标签的enctype 属性
Andre Villeneuve

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • 在之前的文章中,小白已经帮大家搞定了文件上传的关键技术。文件上传搞定了,下面我们要做的就是要对上传的文件进行操作,...
    丁建雄阅读 575评论 0 3
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,434评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 看过很多关于二战的摄影作品,今天听了李颀拯的演讲及作品,还是很有感触。中国经济在飞速发展,人民生活水平逐渐提高...
    追风筝的女孩CN阅读 535评论 2 0
  • ✎✎#幸福是需要修出来的~每天进步1%~幸福实修09班~19-姓名雅楠 【幸福三朵玫] 昨日两朵玫瑰 迅速完成工作...
    幸福实修09班19号雅楠阅读 187评论 0 0