蹊蹺

2013-03-15 67 views
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

有什麼不對?

+1

請使用換行符來提高可讀性。 – deceze 2013-03-15 13:23:35

+0

出於好奇你有沒有試過'$ target_path ='。/ uploads /'.$ year。'/'。$ month。'/'。$ date。'/'。$ _ FILES [「image_name」] [「name」 ];'? – 2013-03-15 13:24:09

+0

對不起,我這裏是新的 – User 2013-03-15 13:24:23

回答

4

首先,關於文件上傳的一般注意事項:typename密鑰是不安全的。這是因爲它們是由客戶定義的,它們是將惡意代碼注入到您的網站的潛在機制。考慮如果我將文件名設置爲../../../../../index.php,或者如果我將MIME類型設置爲image/gif,但是上傳了PHP文件,會發生什麼情況?

接下來,具體說明圖片上傳的重要提示:您不能相信客戶端上傳的圖片數據。也可以將惡意代碼嵌入看起來像圖像一樣的東西。您需要將像素數據從文件中複製出來並創建一個新的。這通常用GD擴展來完成。

接下來,在mkdir() - 它有第三個參數,如果您將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 />'); 
} 

不過,我不會這麼做。

文件上傳是一個非常普遍的任務,我使用的通用代碼看起來像this。看起來很複雜不是嗎?那是因爲處理文件上傳並不簡單。然而,這種複雜性提供了一個很好的直接方式來解決上面列出的安全問題。它內置了對圖像的支持,包括用乾淨簡單的方式調整大小的選項。

讓我們來看看我們如何可以在你的代碼中使用它:

$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()); 
    } 
} 

這做了很多事情的背景來解決安全問題我在前面列出。它會自動檢測到圖像是有效的,識別的類型,並將正確的文件擴展名應用於保存的文件。

0

一個快速的答案,潛在的代碼問題:

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

這需要第二次的mkdir:

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

之後,但是 - 你結束與設置$target_path

的代碼示例我們需要看看在設置$target_path之後會發生什麼,以便我們看到變量和輸出之間會發生什麼變化。

在調試過程中,我建議在設置它之後立即快速將其值輸出到日誌文件中,看看它是否正確,但稍後再進行更改。

+0

沒有任何變化,之後我直接將其添加到數據庫 – User 2013-03-15 13:41:17

+0

啊,有用的信息。但是,我們仍然無法看到該代碼,因此我們無法對其進行評論。但是,快速思考 - 數據庫列的字符限制是什麼? – 2013-03-15 13:45:01

+0

字符限制爲200 – User 2013-03-15 13:46:32