首頁  >  文章  >  後端開發  >  PHP檔案上傳偵測及處理

PHP檔案上傳偵測及處理

墨辰丷
墨辰丷原創
2018-06-05 16:04:454136瀏覽

本篇主要介紹PHP檔案上傳檢測及處理,有興趣的朋友參考下,希望對大家有幫助。

input方式的上傳就如此之差麼?當然不是。上傳檔案不大的時候,它還是非常簡單可靠的,在PHP中,我們只需要一個複合型表單:

程式碼如下:

<form enctype="multipart/form-data" action="__URL__" method="POST">

一個輸入框:

 程式碼如下:

<input name="userfile" type="file" />

與伺服器端的一行程式碼:

 程式碼如下:

move_uploaded_file($_FILES[&#39;userfile&#39;][&#39;tmp_name&#39;], &#39;/var/www/uploads/&#39;. basename($_FILES[&#39;userfile&#39;][&#39;name&#39;]));

就可以實作整個上傳過程。
但隨文件增大,表單上傳的不足就會暴露出來。尤其是我們想取得最基本的檔案大小來阻止過大檔案上傳這個簡單的想法,也變得如此困難。以下一一道來:
透過MAX_FILE_SIZEMAX_FILE_SIZE 隱藏欄位(單位為位元組)必須放在檔案輸入欄位之前,其值為接收檔案的最大尺寸。這是對瀏覽器的建議,PHP 也會檢查此項目。在瀏覽器端可以簡單繞過此設置,因此不要指望用此特性來阻擋大型檔案。實際上,PHP 設定中的上傳檔案最大值是不會失效的。但最好還是在表單中加上此項目,因為它可以避免用戶在花時間等待上傳大檔案之後才發現檔案過大上傳失敗的麻煩。
顯然PHP的開發者們也考慮到了大文件上傳的問題,但就像手冊所說,MAX_FILE_SIZE只是對瀏覽器的一個建議,事實上目前為止所有主流的瀏覽器並沒有採納這個建議,所以採用MAX_FILE_SIZE約束檔案大小形同擺設,不可行。
透過伺服器端MAX_FILE_SIZE既然無效,那麼使用者可以將檔案上傳到伺服器,伺服器端透過$_FILES['userfile']['size']判斷使用者上傳的文件大小,然後決定是否接受上傳並返回訊息。暫且排除伺服器的負載以及可能存在的惡意破壞行為,這種解決方案聽起來無非是浪費一部分頻寬,也能對使用者 上傳檔案作出約束。
但這也是不可行的,PHP的檔案上傳受到php.ini以下這些設定的影響:

  • #post_max_size

  • upload_max_filesize

  • max_execution_time

  • memory_limit

#雖然設定方法在手冊中都有比較詳細的說明,之所以還是說此方法不可行,是因為php執行腳本在超過memory_limit時,該次的POST資料會全部遺失且不會報錯!
試想用戶填寫了一個超長的表單,並伴隨一個超過memory_limit的文件一起上傳,經過了漫長的等待時間之後發現等來的又是一張乾乾淨淨的空白表單,那是何等印象深刻的使用者體驗啊。更何況數十M的伺服器流量僅用來偵測檔案大小,是現在的網路環境不允許的。
透過JavascriptJavascript是基於瀏覽器的,雖然JS能完成很多看似不可能的任務,但瀏覽器做不到的事情JS同樣無法做到。先天不足注定了這份工作僅靠Javascript是無法勝任的。不過有些IE Only的方法 也還是存在的,僅作參考 。
透過FlashFlash的FileReference類別提供了一套比較全面的檔案處理方法,現在大多數大檔案上傳也都採用了基於Flash的方案。如果利用Flash與Js交互,能否實現客戶端對檔案大小的偵測呢?答案是可行的。
首先在flash檔案中實例化FileReference類別。

var fr = new FileReference();

基於這個類別就可以用Flash提供的file browse和SelectFile事件來取代瀏覽器的事件。我們需要:
1、綁定SelectFile

fr.addEventListener(Event.SELECT, onSelectFile);

2、建立一個供Js存取的對象,用來放置flash得到的檔案資訊

var s = {
 size:0,
 name:&#39;&#39;,
 type:&#39;&#39;
}

3、建立file browse方法

function browseFile():void {<br>
 fr.browse();<br>
}

4、當SelectFile事件觸發的時候,傳遞檔案訊息

function onSelectFile(e:Event):void {<br>
 s.size = fr.size;<br>
 s.name = fr.name;<br>
 s.type = fr.type;<br>
}

5、將browseFile方法公開可供Js呼叫

ExternalInterface.addCallback("browseFile", browseFile);

6、將得到的檔案資訊傳遞給Js

#
ExternalInterface.call("onSelectFile",s);

现在我们已经可以通过Js获得由flash传递来的文件大小信息了,具体的实现可以参看Demo 。
结论
问题至此似乎已经得到解决了,我们已经成功的校验了文件大小不是么。但本文的最终结论是,基于Flash的文件大小校验,仍然不可行。
文件大小校验的唯一目的,是为了上传。在上面的Demo中可以看到校验成功的文件名会显示在一个输入框里。熟悉上传的同学不觉得少了什么吗?没错,通过 flash只能得到文件名,而无法得到文件的完整路径,而文件路径却是input方式上传的必要条件。所以虽然可以成功的通过Flash与Js交互校验文 件大小,但我们能做到的也仅仅只是校验而已,之后想要上传,唯有继续通过flash方式进行。
Flash开发出于安全考虑屏蔽了文件的完整路径这无可厚非,不过文件上传,尤其是PHP环境下的文件校验上传方案仍然没有得到最好的解决。
当然弥补的方法有很多:

基于Perl的项目 FileChucker , XUpload , Uber-Uploader基于Flash的项目 SWFUpload还有筒子用PHP直接 在服务器华丽的建立socket链接

但终究我希望有一天能看到仅基于HTML就能实现的严整健壮的上传方案,但愿这一天不会太远。
最后是本次的代码下载 。
php文件上传大小设置详解用php上传文件,问题最多的就是上传大体积文件时出现错误。 这就涉及到php的配置文件——php.ini
在此配置文件中,有这么几个值是跟文件上传有密切关系的:

  • file_uploads = on //是否允许系统支持文件上传

  • upload_tmp_dir //临时文件的存储路径,linux下为系统默认路径,win32下需要指定

  • upload_max_filesize = 2m //允许文件上传最大体积

  • post_max_size = 2m //通过post方法给php时,php所能接受的最大数据容量

如果你上传的文件体积在8m一下(通常情况),那修改以上设置就可以满足你的要求了。
但要>8m,那除了上面几个值,还要特别关注另外两个值了:

  • max_execution_time = 30 //每个script所执行的最大时间(php上传就时,体积大了,就是个时间问题)

  • memory_limit = 8m //每个script所能消耗的最大memory

试着把这两个值改大些。一般就可以解决大多数问题了。

就此推断,上传文件的体积是可以无穷大的。但还要考虑你的网络情况,等等。
在php.net上,有人说按照这个方法改了后,大于100m的文件还是会出错,不知道是不是PHP本身的问题了。

总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。

相关推荐:

PHP中基于sleep函数实现定时执行功能的方法

PHP 输出缓冲控制详解

php 输入输出流详解及实例分析

以上是PHP檔案上傳偵測及處理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn