0

申し訳ありませんが、私はここで新しいです、あなたが尋ねた後、私は完全なコードを追加しました:そして私は私のコードが悪いことを知っています:)

if ((($_FILES["image_name"]["type"] == "image/gif")
   ($_FILES["image_name"]["type"] == "image/jpeg")
   ($_FILES["image_name"]["type"] == "image/png")
   ($_FILES["image_name"]["type"] == "image/pjpeg")))
  {
  $year = date('y');
  $month = date('m');
  $date = date('d');
    if(file_exists('./uploads/'.$year)){ 
        if(file_exists('./uploads/'.$year.'/'.$month)){
            if(file_exists('./uploads/'.$year.'/'.$month.'/'.$date)){ 
                $target_path='./uploads/'.$year.'/'.$month.'/'.$date.'/'.$_FILES["image_name"][‌​"name"];
            }
            else{
                mkdir('./uploads/'.$year.'/'.$month.'/'.$date);
            }
        }
        else{
            mkdir('./uploads/'.$year.'/'.$month);
        }     
}
else{
    mkdir('./uploads/'.$year);
    mkdir('./uploads/'.$year.'/'.$month);
    mkdir('./uploads/'.$year.'/'.$month.'/'.$date);
}
  if ($_FILES['image_name']['error'] > 0)
    {
    echo 'Return Code: ' . $_FILES['image_name']['error'] . '<br />';
    }
    else
      {
      move_uploaded_file($_FILES['image_name']['tmp_name'],
      './uploads/'.$year.'/'.$month.'/'.$date.'/'.$_FILES['image_name']['name']);
      $target_path='./uploads/'.$year.'/'.$month.'/'.$date.'/'.$_FILES["image_name"][‌​"name"];
      }
  }

$target_path変数は次のように出力されます。

アップロード/13/03/15/image_name.jpg

しかし、それは印刷します:

s / 13/03/15 / image_name.jpg

どうしたの?

4

2 に答える 2

4

まず、一般的なファイルのアップロードに関する重要な注意事項:キーtypenameキーは安全に使用できません。これは、これらがクライアントによって定義されており、サイトに悪意のあるコードを挿入するための潜在的なメカニズムであるためです。../../../../../index.phpファイル名をに設定した場合、またはMIMEタイプをに設定したimage/gifが、代わりにPHPファイルをアップロードした場合はどうなるか考えてみてください。

次に、画像のアップロードに関する重要な注意事項:クライアントによってアップロードされた画像データは信頼できません。画像のように見えるものに悪意のあるコードを埋め込むことも可能です。ファイルからピクセルデータをコピーして、新しいピクセルデータを作成する必要があります。これは通常、GD拡張機能を使用して実現されます。

次に、mkdir()-に3番目の引数があります。この3番目の引数に渡すtrueと、ディレクトリツリーが再帰的に作成されるため、個別の操作で各レベルを作成する必要はありません。また、(多くのことと同様に)mkdir()失敗する可能性があることにも注意してください。これが発生した場合は、が返さfalseれます。これを確認する必要があります。

さて、実際の質問に答えるために(そして前述のセキュリティ問題を少し無視して)、これがあなたのコードを単純化する方法です:

// Configuration
$allowedTypes = array(
    "image/gif", "image/jpeg", "image/png", "image/pjpeg"
);
$baseDir = './uploads';

// Check file was uploaded successfully
if ($_FILES['image_name']['error'] > 0) {
    exit('Return Code: ' . $_FILES['image_name']['error'] . '<br />');
}

// Check file type
if (!in_array($_FILES["image_name"]["type"], $allowedTypes)) {
    exit('Invalid file type: ' . $_FILES['image_name']['type'] . '<br />');
}

// Check/create target directory
list($year, $month, $day) = explode('-', date('y-m-d'));
$targetDir = $baseDir . '/' . $year . '/' . $month . '/' . $day;
if (!is_dir($targetDir)) {
    if (!mkdir($targetDir, 0644, true)) {
        exit('Failed to create destination directory<br />');
    }
}

// Store the uploaded file permanently
$targetPath = $targetDir . '/' . .$_FILES['image_name']['name'];
if (!move_uploaded_file($_FILES['image_name']['tmp_name'], $targetPath)) {
    exit('Failed to move temporary file<br />');
}

しかし、私はこれをしません。

ファイルのアップロードは非常に一般的なタスクであり、私が使用する一般的なコードは次のようになります。複雑そうですね。それは、ファイルのアップロードの処理が簡単ではないためです。ただし、その複雑さは、上記で概説したセキュリティ上の懸念に対処するための優れた簡単な方法を提供することです。画像のサポートが組み込まれており、サイズを変更してクリーンで簡単な方法で変更するオプションが含まれています。

コードでどのように使用するかを見てみましょう。

$baseDir = './uploads';

// Very simple autoloader for demo purposes
spl_autoload_register(function($class) {
    require strtolower(basename($class)).'.php';
});

// When you instantiate this the $_FILES superglobal is destroyed
// You must access all uploaded files via this API from this point onwards
$uploadManager = new \Upload\Manager;

// Fetches a FileCollection associated with the named form control
$control = $uploadManager->getControl('image_name');

// getControl returns NULL if there are no files associated with that name
if (!isset($control)) {
    exit('No file was uploaded in the image_name control');
}

// Check/create target directory
// You still need to do this, it's not magic ;-)
list($year, $month, $day) = explode('-', date('y-m-d'));
$targetDir = $baseDir . '/' . $year . '/' . $month . '/' . $day;
if (!is_dir($targetDir)) {
    if (!mkdir($targetDir, 0644, true)) {
        exit('Failed to create destination directory');
    }
}

// This also handles multiple uploads in a single control, so we need to loop
foreach ($control as $image) {
    // You need to determine a file name to use, most likely not from user
    // input. This is a high-entropy low collision-risk random approach.
    $targetFile = $targetDir . '/' . uniquid('upload-', true);

    try {
       $image->save($targetFile, true, IMAGETYPE_ORIGINAL);
    } catch (\Exception $e) {
       exit("Oh noes! Something went badly wrong: ".$e->getMessage());
    }
}

これは、前に概説したセキュリティ上の懸念に対処するために、バックグラウンドで多くのことを行います。画像が有効で認識されたタイプであることを自動的に検出し、保存されたファイルにも正しいファイル拡張子を適用します。

于 2013-03-15T14:11:28.993 に答える
0

潜在的なコードの問題に対する1つの簡単な答え:

else{
    mkdir('./uploads/'.$year.'/'.$month);
}

これには2番目のmkdirが必要です。

else{
    mkdir('./uploads/'.$year.'/'.$month);
    mkdir('./uploads/'.$year.'/'.$month.'/'.$date);
}

ただし、その後は、コード例を次のように設定して終了します。$target_path

設定後に$target_path何が起こるかを確認する必要があるため、作成と出力の間に変数がどうなるかを確認します。

デバッグ中は、設定後すぐにログファイルに値をすばやく出力して、その時点で問題がないかどうかを確認することをお勧めしますが、後で変更します。

于 2013-03-15T13:38:42.273 に答える