PHP之文件的鎖定、上傳與下載的方法

1.文件鎖定php

如今都在講究什麼分佈式、併發等,實際上文件的操做也是併發的,在網絡環境下,多個用戶在同一時刻訪問頁面,對同一服務器上的同一文件進行着讀取,若是,這個用戶恰好讀到一半,另外一個用戶就寫入了消息,那麼前一個用戶讀到的就是錯誤數據,在數據庫裏面好像是稱爲髒數據,而若是某用戶寫到一半時,另外一用戶也對該文件進行寫操做,那麼就形成了寫入數據的混亂和錯誤,所以�php有一個鎖機制,相似於數據庫的鎖,當某用戶在對文件操做時就加上某種鎖,使得在同一時間其餘用戶不能對該文件進行操做或只能進行有限的操做,來保證在這些狀況下的文件數據的正確性。面試

主要使用flock函數,原型:bool flock(resource $handle , int $operation [, int &$wouldblock ]),第一個參數是指向文件的句柄變量,第二個是加鎖的方式,分別爲數據庫

LOCK_SH:共享鎖(share),在讀取文件時加的鎖,加鎖後就其餘用戶不能再對該文件進行寫,但能夠讀取該文件內容;windows

LOCK_EX:排他鎖(exclude),或者叫獨佔鎖,在寫文件時使用,加了該鎖後,只能是當前用戶進行寫操做,其餘的用戶不能讀取和寫入;安全

LOCK_NB:附加鎖,在文件鎖定短期大量用戶的訪問操做可能會形成flock在鎖定時堵塞,若是再加上該鎖後可避免該狀況(是否是這麼一弄就能解決大量讀寫操做的問題,怕不行...);服務器

LOCK_UN:釋放鎖,對前面的各類鎖進行一次性釋放,解鎖。網絡

若是容易堵塞,還可以使用第三個參數wouldblock,若是把它設置爲1,在鎖定後就會阻擋其餘進程來進行一些操做,可是windows上不支持,另外附加鎖LOCK_NB,windows也是不支持的。多線程

另外,關閉句柄變量的fclose操做也能夠釋放這些鎖。併發

廢話少說,看代碼 分佈式

複製代碼

<?php

function readFileData($filename){

if(true == ($handle = fopen($filename, 'r'))){

if(flock($handle, LOCK_SH+LOCK_NB)){ // 加共享鎖和附加鎖,附加鎖防止阻塞

$str = '';

while(!feof($handle)){

$str .= fread($handle, 128);

}

flock($handle, LOCK_UN); // 釋放該鎖

fclose($handle);

return $str;

}

else{

echo 'add a share lock failed';

return '';

}

}

else{

return '';

}

}

複製代碼

注意使用多重鎖的方式,是LOCK_SH+LOCK_NB,,在排他鎖時也可這麼用,它們都是枚舉變量。對於寫操做相似

複製代碼

<?php

function writeInFile($filename, $data){

if(true == ($handle = fopen($filename, 'a'))){

if(flock($handle, LOCK_EX)){ //加上排他鎖

fwrite($handle, $data);

flock($handle, LOCK_UN); //釋放鎖

fclose($handle);

}

else{

echo 'add exclusive lock failed';

return;

}

}

}

複製代碼

實際上這也是解決php來實現多進程/線程讀取文件的方式,php沒有多線程這麼一說,但加鎖機制能夠來模擬這種方式,實現對文件某些操做的隊列處理,面試時別說你不知道-_-

2.文件上傳

文件上傳就是將本地的文件上傳到服務器上,咱們在用度場的雲、鵝場的雲上傳文件時均是如此,固然實際狀況確定比這簡單程序複雜。HTTP協議實現了文件的上傳機制,首先要在本地選擇上傳的文件,上傳到服務器後,服務端又要作一些處理,爲此客戶端和服務端均要作一些設置。

一、客戶端

文件上傳最基本的方法是經過form表單進行POST傳遞文件,實際上經過PUT方法也能夠上傳文件,只不過這種方法不安全,須要配置一些安全驗證機制,這裏只寫最經常使用的方式。form表單的input標籤能夠設置成文件上傳按鈕type="file",直接解決了如何選擇文件的問題,接下來須要設置form的兩個屬性:enctype和method

enctype:設置成multipart/form-data

method:設置成post

關於enctype屬性設置可參考W3School的解釋

 

第一條是默認的值,在咱們使用HTTP協議傳遞通常的表單數據時,實際上默認對數據進行了分塊編碼,好比默認的urlencode方式(空格轉爲+,其餘非字母字符轉爲%加兩個十六進制大寫數);當enctype設置爲第二個時,不會進行字符編碼,使用上傳控件(input標籤type設爲file時便是)上傳文件,必須設定爲這個值;第三個則是值對空格編碼爲+,但不對非字母字符進行編碼。

咱們知道GET方法通常用於獲取數據,且傳遞數據大小有限,並且POST方法能夠傳遞比GET大得多的數據。

form的屬性設置完成後,還要傳遞一個值過去,使用隱藏域(<input type="hidden">),它的name屬性設爲MAX_FILE_SIZE,之因此要設定這個值,是先大概定一個文件尺寸值,避免在用戶傳一個大文件傳了半天再告訴他:sorry,你的文件太大了-_-它的value屬性值就是文件的size,以字節爲單位。固然某些書上說,這個值只是做爲參考,可輕易進行欺騙,這裏只是象徵性的表示,很惋惜我這隻菜鳥對安全瞭解甚少,只知道普通注入、XSS等,暫且用着吧。

那麼就能夠寫一個簡單得不能再簡單的頁面了,做爲客戶端用:

<form method="post" action="upload.php" enctype="multipart/form-data">

<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />

選擇文件: <input type="file" name="uploadFile" value="upload"/><br/>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

<input type="submit" name="submit" value="上傳" />

</form>

相關文章
相關標籤/搜索