PHP ファイルのロック、アップロード、ダウンロード
ファイルのロック機構、アップロードとダウンロードの概要
1. ファイルロック
現在、私たちは分散、同時実行性などに注目しています。実際、ネットワーク環境では、複数のユーザーが同時にページにアクセスし、同じサーバー上の同じファイルを読み取ります。ユーザーが読み取り途中で、別のユーザーがメッセージを書き込むと、前のユーザーが読み取ったデータはデータベース内のダーティ データと呼ばれるようになります。また、書き込み途中のユーザーは、別のユーザーもメッセージを書き込みます。ファイルが書き込まれると、書き込まれたデータに混乱やエラーが発生する可能性があるため、PHP には、ユーザーがファイルを操作するときに、特定のロックが追加されるロック メカニズムがあります。このような状況では、他のユーザーはファイルを操作できないか、ファイル データの正確性を確保するための限られた操作しか実行できません。
主に flock 関数を使用します。プロトタイプ: bool flock(resource $handle, int $operation [, int &$wouldblock])、最初のパラメータはファイルを指すハンドル変数、2 番目のパラメータはそれぞれロックメソッドです
LOCK_SH: 共有ロック (共有)、ファイルの読み取り時に追加されるロック。ロック後は、他のユーザーはファイルに書き込むことができなくなりますが、ファイルの内容を読み取ることができます。
LOCK_EX: 排他ロック (除外) は、ファイルの書き込み時に使用されます。このロックを追加すると、現在のユーザーのみが書き込み操作を実行でき、他のユーザーは読み書きできなくなります。
LOCK_NB: 追加のロック。ファイルがロックされている場合、短期間に多数のユーザー アクセス操作が行われると、ロック中にブロックが発生する可能性があります。このロックを追加すると、この状況を回避できます。大量の読み取りおよび書き込み操作を解決するために行われたのですか? 質問、うまくいかないのではないかと思います...);
LOCK_UN: ロックを解除し、以前のロックを一度に解除およびロック解除します。
ブロックするのが簡単な場合は、3 番目のパラメータ wouldblock を使用することもできます。これを 1 に設定すると、ロック後に他のプロセスの一部の操作がブロックされます。ただし、追加のロックは Windows ではサポートされていません。 LOCK_NB は Windows ではサポートされていません。
さらに、ハンドル変数を閉じる fclose 操作でもこれらのロックを解放できます。
くだらない話はやめて、コードを見てください
コードをコピー
関数readFileData($filename){
if(true == ($handle = fopen($filename, 'r'))){
if(flock($handle, LOCK_SH+LOCK_NB)){// 共有ロックと追加ロックを追加し、ブロックを防ぐための追加ロックを追加します
$str = '';
while(!feof($handle)){
}
flock($handle, LOCK_UN) // ロックを解除します
fclose($handle);
$ Str を返します。
}
それ以外{
echo '共有ロックの追加に失敗しました';
戻る '';
}
}
他{
戻る '';
}
}
コードをコピー
複数のロックを使用する方法は、排他的ロックにも使用できる LOCK_SH+LOCK_NB であることに注意してください。これらはすべて列挙型変数です。書き込み操作についても同様です
コードをコピー
関数 writeInFile($filename, $data){
if(true == ($handle = fopen($filename, 'a'))){
C If (FLOCK ($ Handle, LOCK_EX)) {// 彼にロックを追加します
fwrite($handle, $data);
flock($handle, LOCK_UN); // ロックを解放します
fclose($handle);
}
else {
echo '排他ロックの追加に失敗しました';
戻る;
}
}
}
コードをコピー
実際、これはファイルのマルチプロセス/スレッド読み取りを実現するために PHP を解決する方法でもあります。PHP にはマルチスレッドがありませんが、ロック機構はこの方法をシミュレートし、ファイルに対する特定の操作のキュー処理を実現できます。面接中は知らないとは言わないでください-_-
2. ファイルのアップロード
ファイルのアップロードは、ローカル ファイルをサーバーにアップロードすることです。これは、Duchang のクラウドと Echang のクラウドを使用してファイルをアップロードする場合です。もちろん、実際の状況はこの単純な手順よりも確実に複雑です。 HTTP プロトコルはファイル アップロード メカニズムを実装します。まず、アップロードされたファイルをサーバーにアップロードした後、クライアントとサーバーの両方でいくつかの処理を行う必要があります。
1. クライアント
ファイルをアップロードする最も基本的な方法は、フォームを使用してファイルを POST することです。ただし、この方法は安全ではないため、いくつかのセキュリティ検証メカニズムを設定する必要があります。最も一般的に使用されるメソッドのみを記述します。フォームの入力タグをファイルアップロードボタン type="file" に設定することで、ファイルを選択する方法の問題を直接解決できます。 次に、フォームの 2 つの属性、enctype と Method
を設定する必要があります。
enctype: multipart/form-data に設定します
方法:投稿に設定
enctype属性の設定についてはW3Schoolの説明を参照してください
最初の値は、HTTP プロトコルを使用して一般的なフォーム データを送信する場合、データは実際には、デフォルトの urlencode メソッドなどのブロックでエンコードされます (スペースは + に変換され、その他の文字以外の文字は変換されます)。 % に変換されます。大文字の 2 つの 16 進数を追加します); enctype が 2 番目に設定されている場合、アップロード コントロールを使用してファイルをアップロードする場合 (つまり、入力タグの種類が file に設定されている場合)、この値は実行されません。 3 番目の値はスペースを + としてエンコードしますが、アルファベット以外の文字はエンコードしません。
データの取得には GET メソッドが一般的に使用され、転送されるデータのサイズには制限があり、POST メソッドは GET よりもはるかに大きなデータを転送できることがわかっています。
フォーム属性を設定した後、値を渡す必要があります。この値を設定する理由は、隠しフィールド () を使用することです。最初に大まかにファイル サイズの値を設定します。大きなファイルを長時間アップロードした後にユーザーに次のようなメッセージが表示されないようにします。申し訳ありませんが、ファイルが大きすぎます -_- その value 属性値はファイルのサイズ (バイト単位) です。もちろん、この値は単なる記号であり、簡単に騙される可能性があると書かれている本もあります。初心者の私はセキュリティについてはほとんど知識がなく、XSS についてしか知りません。 , などがあるので、とりあえず使ってみます。
次に、非常に単純なページを作成し、それをクライアントとして使用できます。
ファイルを選択:
2. サーバー
ファイルがサーバーにアップロードされた後も、オンライン ショッピングや速達と同様に、目的地に到着したときにカテゴリに分類される必要があります。宛先での後続の処理には、PHP スクリプトが必要です。上記のフォームを送信するときの action 属性は、送信処理スクリプトを指定します。 php では、$_POST が post で渡されたデータを保存し、アップロードされたファイルの関連情報が $_FILES に保存されることがわかっています。サーバー スクリプトが次のようになっていると仮定します。
print_r($_FILES);
print_r($_POST);
サーバーがどのように処理するかに関係なく、まずこれら 2 つの配列の内容を見てみましょう:
FILES 配列のオプションを見れば推測できます。これらは、アップロードされたファイルの名前、タイプ、サイズ、エラー メッセージなどです。また、FILES は 2 次元配列です。これらのオプションを理解する前に、php.ini ファイルを開いて次の 4 つの項目を見つけてください (実際、コメントを読むことで理解できます)。
file_uploads: HTTP を介したファイル転送を許可するかどうか、デフォルトはオンです。
Upload_max_filesize: 転送が許可されるファイルの最大サイズ (M)、これはサーバー構成ファイルによって設定されるオプションです。
max_file_uploads: 1 つのリクエストで渡すことができる複数のファイルの数
Post_max_size: POST を通じて転送されるデータの最大サイズ。ファイル転送もポスト転送とみなされます。これは、ファイルだけではないため、upload_max_filesize オプションより大きくする必要があることに特別な注意を払う必要があります。転送後のアップロード中にアップロードされますが、上記の POST 配列のデータなど、他の値を渡すことも考慮する必要があります。たとえば、upload_max_filesize が 150M に設定されている場合、これを 200M に設定できます。
Upload_tmp_dir: ファイルをアップロードするための一時ディレクトリ。設定ファイルではデフォルトで空になっています。そのため、上記の FILES 配列の tmp_name にあるおなじみのパスが使用されます。 Windows はデフォルトで一時ファイルを保存するディレクトリにあり、サーバーはデフォルトでファイル名を変更しています。
では、FILES 配列の UploadFile はどこから来て、なぜそれをキー名として使用するのでしょうか? これは、アップロード コントロールの name 属性が、このコントロールのアップロード ファイル情報をマークするためです。もちろん、
のように、すべてを同じ名前に設定することもできます。
ここで、FILE 配列のキー名で表される情報を見てください。Type は / で区切られた MIME タイプで、後ろは特定のファイル タイプです。いくつかの状況があります。0: エラーなし、アップロードは成功しました。1: ファイルが PHP 構成ディレクティブの Upload_max_filesize で指定されたサイズを超えています。2: ファイルが HTML フォームの MAX_FILE_SIZE で指定されたサイズを超えています。部分的にのみアップロードされます。4: ファイルはアップロードされません。これで、FILES 配列に関するすべての問題が理解できました。
問題は、アップロードが成功した場合、処理は行われないということです。もちろん、ファイルをアップロードしすぎると、ファイルを他の場所に移動することになり、一時ディレクトリに蓄積することはできません。特化した安全な機能を提供します。 is_uploaded_file 関数は、HTTP POST 経由でアップロードするかどうかを決定します。これにより、悪意のあるユーザーがスクリプトをだまして、これらのファイル (/etc/pass (また Linux です...) など) を管理できるようになります。具体的な詳細については、わかりません。まだ。 move_uploaded_file 関数は、アップロードされたファイルを新しい場所に移動し、ファイルが正当にアップロードされたかどうか、つまり HTTP POST 経由でアップロードされたかどうかを判断することもできます。正常に実行された場合は、ブール型の true を返します。
長い間話した後、ファイルをアップロードするには次の手順が必要になる可能性があります:
1. クライアントはアップロード制御スクリプトを作成し、ファイル サイズを制限する非表示の値を渡します。
2. サーバーはまず FILES 配列のエラー値を判断し、エラーがあるかどうかを確認します。
3. アップロードを許可するタイプかどうかを判断します (判断する必要はありません)。
4. 指定されたファイル サイズがサーバー スクリプトで指定されたファイル サイズを超えているかどうかを確認します。
5. 一時的な場所にアップロードし、新しいファイル名を生成し (同じ名前の既存のファイルが上書きされるのを防ぐため)、確認して新しいディレクトリに移動します。
クライアントの準備作業が完了しました。サーバー処理コードを見てください:
コードをコピー
$typeWhiteList = array('txt', 'doc', 'php', 'zip', 'exe'); // ホワイトリストを入力し、アップロードが許可されていないファイルの種類をフィルタリングします
$max_size = 1000000 // サイズ制限は 1M です
;
$upload_path = 'D:/WAMP/upload/' // 移動先のディレクトリを指定します
;
// 1. サーバーへのアップロードが成功したかどうかを確認します
$error = $_FILES['uploadFile']['error'];
if($error > 0){
switch($error){
E ケース 1: 終了 (「アップロードできるファイルの最大数が pHP 設定を超えている」)
E ケース 2: 終了 (「HTML フォームの最大ファイルのアップロード制限を超える」);
ケース 3: exit('ファイルの一部のみがアップロードされました');
ケース 4: exit('ファイルがアップロードされていません');
デフォルト: exit('不明な型エラー');
} }
}
// 2. アップロードの種類が許可されているかどうかを判断します
$extension = pathinfo($_FILES['uploadFile']['name'], PATHINFO_EXTENSION) // 拡張子を取得します
if(!in_array($extension, $typeWhiteList)){
if($extension == '')
'終了 (' 空のタイプのファイルをアップロードすることはできません ');
その他
'終了 (' ファイルを入力 ');
}
// 3. 許可されたサイズかどうかを判断します
if($_FILES['uploadFile']['size'] > $max_size){
'終了 (' 許可されている以上のアップロード '. $ Max_size.' バイト ');
}
// 4. 指定された場所に到着しました
$filename = date('Ymd').rand(1000, 9999); // 上書きを防ぐために新しいファイル名を生成します
if(is_uploaded_file($_FILES['uploadFile']['tmp_name'])){ // HTTP POST 経由でアップロードするかどうかを決定します
if(!move_uploaded_file($_FILES['uploadFile']['tmp_name'], $upload_path.$filename.'.'.$extension)){
。
} }
他{
文 Echo 'ファイルは正常にアップロードされました & lt;
echo 'ファイル名: '.$upload_path.$filename.'.'.$extension.'
';
} }
}
その他{
exit('ファイルは合法的なルートを通じてアップロードされませんでした');
}
コードをコピー
すぐに試したかったのですが、時間設定はシステムに依存するという警告が報告されました...バグは常に予期せず発生します。時間を設定してもう一度試してください。完璧です!
3. ファイルのダウンロード
ファイルのダウンロードは比較的簡単で、HTML リンクを使用してリソースの場所を指定するだけです。ただし、この方法で処理できるのは、rar、7z、その他の圧縮データなど、ブラウザがデフォルトで認識できない MIME タイプのみです。
コードをコピー