PHP ファイルのアップロードに関連する原則について詳しく説明しますので、必要な方は参考にしてください。
多くの PHP チュートリアルでファイルのアップロードが紹介されていますが、今日はその原理を分析します。 //マルチパート/フォームデータエンコーディング形式を使用する $_FILES システム関数; $_FILES['myFile']['name']ファイル名 $_FILES['myFile']['type'] ファイル タイプ、サーバーによって制限されます 画像/** 画像/x-png application/x-zip-compressed $_FILES['myFile']['size']アップロード ファイル サイズ $_FILES['myFile']['tmp_name'] は、サービスのアップロード後に一時ファイル名を保存します $_FILES['myFile']['error'] エラー コード; 0 成功 1 php.ini サイズを超えました 2 MAX_FILE_SIZE オプションで指定された値を超えました 3部分アップロードのみ 5アップロードファイルサイズは0 move_uploaded_file (一時ファイル、ターゲットの場所、ファイル名); アップロード後にファイルを目的の場所に移動する機能 is_uploaded_file(MIME); アップロードの MIME タイプを決定する例: 1.html部分 リーリー2. ファイルアップロードコード リーリー----------------------------------------------- PHPファイルアップロードの原理と実装 1. フォーム 1. ファイルをアップロードするためのフォームは post メソッドを使用します (get との違いは言うまでもありません)。また、enctype='multipart/form-data' を追加します。 2. 通常、隠しフィールドを追加する必要があります: 、ファイル フィールドの前にあります。 value の値は、ファイルをアップロードするためのクライアントのバイト制限です。規格を超えたファイルの場合にクライアントの待ち時間を短縮できるとのことですが、違いはないと思います。 3. セキュリティ上の理由から、ファイルフィールドに値を割り当てることはできません。ファイルフィールドに文字列を入力して送信を押すだけですが、何も起こりません。送信では、2 番目の文字がコロンである場合にのみ「サービス」に同意する必要があります (たとえば、スペースとコロンが続く場合は、長さが 0 バイトの「ファイル」をアップロードできます)。ただし、これはクライアント側の措置であり、過去の MAX_FILE_SIZE と同様に簡単に回避できます。 2番目、ファイルアップロードエラーコード まず段落をコピーします。定義済み変数 $_FILES 配列には 5 つの内容があります。 $_FILES['userfile']['name'] - クライアント マシン ファイルの元の名前 $_FILES['userfile']['type'] - ファイルの MIME タイプ $_FILES['userfile']['size']—アップロードされたファイルのサイズ (バイト単位) $_FILES['userfile']['tmp_name']—ファイルのアップロード後にサーバーに保存される一時ファイル名 $_FILES['userfile']['error']——ファイルアップロードに関連するエラーコード このうち、$_FILES['userfile']['error'] は次の値と意味を持つことができます。 0 - エラーは発生せず、ファイルは正常にアップロードされました。 1 - アップロードされたファイルは、php.ini の Upload_max_filesize オプションの制限を超えています。 2 - アップロードされたファイルのサイズが、HTML フォームの MAX_FILE_SIZE オプションで指定された値を超えています。 3 - ファイルの一部のみがアップロードされました。 4 - ファイルはアップロードされませんでした。 1~3は言うまでもありません。 「ファイルはアップロードされませんでした」(4) は、フォームのファイル フィールドにコンテンツがなく、空の文字列であることを意味します。 「ファイルが正常にアップロードされました」(0) は、必ずしもファイルが実際にアップロードされたことを意味するわけではありません。たとえば、ファイル フィールドに「c:」と入力すると、「アップロード成功」と表示されます。エラー コードは 0、['name'] は "c:"、['type'] は "application/octet" です。 -stream" 、['size'] は 0、['tmp_name'] は "xxx.tmp" (xxx はサーバーによって指定された名前) 3. ファイルサイズの制限と検査 アップロードされるファイルのサイズを制限する要因には次のものがあります。 1. クライアントの隠しフィールド MAX_FILE_SIZE の値 (バイパス可能)。 2. サーバー側のupload_max_filesize、post_max_size、memory_limit。これらの項目はスクリプトでは設定できません。 3. ファイル サイズ制限ロジックをカスタマイズします。サーバーの制限を自分で決定できる場合でも、状況によっては個別に考慮する必要がある場合があります。したがって、この制限方法が必要になることがよくあります。 私が遭遇した状況は普遍的ではないかもしれません。説明しましょう。ファイルがサーバー側の制限 (upload_max_filesize) よりもはるかに大きいが、post_max_size またはmemory_limit に達していない、またはそれに近い場合、$_FILES は「崩壊」します。その結果、$_FILES['userfile'] は「未定義のインデックス」になります。 」、もちろんできるテストはありません。 サーバー側の制限の検証は、クライアント側の制限の検証よりも優先されます。つまり、2 つの制限が同じでファイルが大きすぎる場合、$_FILES['userfile']['error'] はエラー コード 1 を発行します。クライアントの制限がサーバーの制限よりもある程度「程度」小さく、ファイル サイズが両方を超えている場合にのみ、エラー コード 2 が表示されます (これが、MAX_FILE_SIZE が期待された役割を果たしていないように感じる理由でしょうか?)。私のマシンでテストした上記の「レベル」は 3 ~ 4K です。私のマシンに設定されているサーバー制限は 2M です...意味がわからないため、正確なルールはありません。 エラーコード 1 または 2 が表示された場合: $_FILES['userfile']['name'] はクライアント マシン ファイルの元の名前です。 $_FILES['userfile']['type'] は空の文字列です $_FILES['ユーザーファイル']['サイズ'] は 0 です $_FILES['userfile']['tmp_name'] は空の文字列です 四,文件路径检验 file域无输入,错误代码为4(无文件上传) $_FILES['userfile']['name']为空字符串 $_FILES['userfile']['type']为空字符串 $_FILES['userfile']['size']为0 $_FILES['userfile']['tmp_name']为空字符串 file域是非文件路径的字符串(不考虑客户端的假“限制”了),错误代码是0(“上传成功”) $_FILES['userfile']['name']为原字符串 $_FILES['userfile']['type']为application/octet-stream $_FILES['userfile']['size']为0 $_FILES['userfile']['tmp_name']为一个暂时文件名 五,is_uploaded_file()的返回值 手册上面不很详细地说,用法是: bool is_uploaded_file( string filename) 实际上 is_uploaded_file($_FILES['userfile']['name']); 总是返回FALSE。后来看见别人是用: is_uploaded_file($_FILES['userfile']['tmp_name']); 比较一下: file域无输入——————返回FALSE——error=>4,name=>'', tmp_name=>'', type=>'', size=>0 file域为非路径字符串——返回 TRUE——error=>0,name=>'xxx',tmp_name=>'yyy',type=>'zzz',size=>0 文件上传成功——————返回 TRUE——error=>0,name=>'xxx',tmp_name=>'yyy',type=>'zzz',size=>sss 文件太大————————返回FALSE——error=>1,name=>'xxx',tmp_name=>'', type=>'', size=>0 文件太大————————返回FALSE——error=>2,name=>'xxx',tmp_name=>'', type=>'', size=>0 文件部分上传——————没机会试验 —error=>3 有点怀疑这个函数是怎么工作的,还是觉得用$_FILES['userfile']['size']检验好些。 六,检验顺序 if($_FILES['userfile']['error']!=4){//有文件上传 if($_FILES['userfile']['error']!=3){//全部上传了 if($_FILES['userfile']['error']!=1){//不超过服务器端文件大小限制 if($_FILES['userfile']['error']!=2){//不超过客户端文件大小限制 if($_FILES['userfile']['size']>0){//确实是文件 if(......){//自定义文件大小检验逻辑 if(......){//自定义文件类型检验逻辑 if(move_uploaded_file($_FILES['userfile']['tmp_name'],...))//移动文件 //.......... } else give_a_message(...); } else give_a_message(...); } else give_a_message(...); } else give_a_message(...); } else give_a_message(...); } else give_a_message(...); } else give_a_message(...); } 附代码: ------------------------------ 1)、test.php: <html> <body> <form enctype="multipart/form-data" action="upload.php" method="POST"> <input type="hidden" name="MAX_FILE_SIZE" value="30000" /> Send this file: <input name="userfile" type="file" accept="image/x-png,image/gif,image/jpeg"/> <input type="submit" value="Send File" /> </form> </body> </html> ログイン後にコピー 2)、upload.php <html> <body> <?php $uploaddir = 'images/'; $uploadfile = $uploaddir. $_FILES['userfile']['name']; print "<pre class="brush:php;toolbar:false">"; if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { print "File is valid, and was successfully uploaded. Here's some more debugging info:\n"; print_r($_FILES); } else { print "Possible file upload attack! Here's some debugging info:\n"; print_r($_FILES); } print " ログイン後にコピー |