最近在學習《HeadFirst PHP & MySQL》一書的第5章“使用存儲在文件中的數據”,做一個文件上傳的應用時,出現了錯誤,就是文件無法成功上傳。這個問題困擾了我很久,不過還好最後終於解決了。原因是我上傳的圖片文件大小超過了HTML 表單中MAX_FILE_SIZE 選項指定的值32768Bytes即32KB導致無法上傳成功。
我使用了XAMPP(Apache + MySQL + PHP + Perl)集成開發包和Zend Studio 10.6作爲PHP IDE開發環境,另外關於PHP調試我採用了XDebug,在Zend Studio10.6中配置Xdebug的PHP調試環境我參考了博文Zend Studio 10.5 與 XDebug 調試| Zend Debugger 說明 Drupal 源代碼 (一)一文。
相應的文件上傳示例PHP代碼addscore.php如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Guitar Wars - Add Your High Score</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h2>Guitar Wars - Add Your High Score</h2>
<?php
require_once 'appvars.php';
require_once 'connectvars.php';
if (isset($_POST['submit'])) {
// Grab the score data from the POST
$name = $_POST['name'];
$score = $_POST['score'];
$screenshot = $_FILES['screenshot']['name'];
if (!empty($name) && !empty($score) && !empty($screenshot)) {
// Move the file to the target upload folder
$target = GW_UPLOADPATH . $screenshot;
echo json_encode($_FILES);
if (move_uploaded_file($_FILES['screenshot']['tmp_name'], $target)) {
// Connect to the database
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)
or die('Error Connecting to MySQL Database!');
// Write the data to the database
$query = "INSERT INTO guitarwars VALUES (0, NOW(), '$name', '$score','$screenshot')";
mysqli_query($dbc, $query) or die('Error querying database;');
// Confirm success with the user
echo '<p>Thanks for adding your new high score!</p>';
echo '<p><strong>Name:</strong> ' . $name . '<br />';
echo '<strong>Score:</strong> ' . $score;
echo '<img src="' . GW_UPLOADPATH . $screenshot . '" alt="Score image" /></p>';
echo '<p><a href="index.php"><< Back to high scores</a></p>';
// Clear the score data to clear the form
$name = "";
$score = "";
$screenshot = "";
mysqli_close($dbc);
}
}
else {
echo '<p class="error">Please enter all of the information to add your high score.</p>';
}
}
?>
<hr />
<form method="post" enctype="multipart/form-data" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<input type="hidden" name="MAX_FILE_SIZE" value="32768" />
<label for="name">Name:</label>
<input type="text" id="name" name="name" value="<?php if (!empty($name)) echo $name; ?>" /><br />
<label for="score">Score:</label>
<input type="text" id="score" name="score" value="<?php if (!empty($score)) echo $score; ?>" /><br />
<label for="screeshot">ScreenShot</label>
<input type="file" id="screenshot" name="screenshot" />
<hr />
<input type="submit" value="Add" name="submit" />
</form>
</body>
</html>
在使用Zend Sutdio10.6設置斷點並調試上面這段PHP代碼時我發現“if (move_uploaded_file($_FILES['screenshot']['tmp_name'], $target)) {”這行代碼裏面的代碼塊沒有執行,於是查看了超全局變量$_FILES['screenshot']['tmp_name']的值爲空,然後我在這行代碼前以JSON格式打印出$_FILES變量的值,如下:
{"screenshot":{"name":"Penguins.jpg","type":"","tmp_name":"","error":2,"size":0}}
相應的運行截圖如下:
然後我查詢$_FILES['screenshot']['error']爲2,上網查詢了一下,關於$_FILES超級全局變量的介紹大體如下:
另外,查詢PHP參考手冊關於move_uploaded_file函數的介紹如下:
move_uploaded_file
(PHP 4 >= 4.0.3, PHP 5)
move_uploaded_file — 將上傳的文件移動到新位置
說明
bool move_uploaded_file ( string $filename , string $destination )
本函數檢查並確保由 filename 指定的文件是合法的上傳文件(即通過 PHP 的 HTTP POST 上傳機制所上傳的)。如果文件合法,則將其移動爲由 destination 指定的文件。
這種檢查顯得格外重要,如果上傳的文件有可能會造成對用戶或本系統的其他用戶顯示其內容的話。
參數
filename
上傳的文件的文件名。
destination
移動文件到這個位置。
返回值
成功時返回 TRUE。
如果 filename 不是合法的上傳文件,不會出現任何操作, move_uploaded_file() 將返回 FALSE。
如果 filename 是合法的上傳文件,但出於某些原因無法移動,不會出現任何操作, move_uploaded_file() 將返回 FALSE。此外還會發出一條警告。
範例
Example #1 Uploading multiple files
<?php
$uploads_dir = '/uploads';
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
}
?>
原因終於找到了,是因爲我上傳了一個超過32768Bytes即32KB大小的Penguins.jpg文件導致出現$_FILES['screenshot']['error']爲2的錯誤,並且$_FILES['screenshot']['tmp_name']爲空,move_uploaded_file($_FILES['screenshot']['tmp_name'],
$target)函數調用時返回FALSE,if (move_uploaded_file($_FILES['screenshot']['tmp_name'], $target)) { ...
}代碼塊沒有執行。