簡體   English   中英

使用 PHP 將圖像上傳到文件夾,同時將描述保存到數據庫

[英]Using PHP to upload images to a folder while saving descriptions to a database

用戶決定為他們的分類列表上傳多張圖片。 我需要做的是:

  1. 上傳帶有每個圖像描述的圖像 - 已解決
  2. 將圖像保存到指定的文件夾
  3. 將圖像位置保存到我的 MySQL 數據庫中,並附上描述 - 已解決
  4. 能夠以畫廊設置的形式調用其分類列表中的圖像和描述

我的表模式是這樣設置的(簡化):

ad_id | member_id | category | subcategory | ... | photo_0_href | photo_0_desc ... | etc.

有人可以指導我完成整個過程嗎? 謝謝。

step3.php

<form action="upload.php" method="post" enctype="multipart/form-data">
<p>
<label for="file0">Filename: </label>
<input name="file[]" type="file" id="file0" size="20" />
</p>
<p>
<label for="file0desc">Description: </label>
<textarea rows="10" cols="30" id="file0desc" class="textarea"></textarea>
</p>
<p>
<label for="file1">Filename: </label>
<input name="file[]" type="file" id="file1" size="20" />
</p>
<p>
<label for="file1desc">Description: </label>
<textarea rows="10" cols="30" id="file1desc" class="textarea"></textarea>
</p>
<p>
<input id="submit" type="submit" name="submit" value="Continue to Step 4" />
</p>
</form>

上傳.php

<?php

if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 1048600)) // less than 1MB
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    header("Location: step4.php");
/*
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

*/
    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>

我知道我的上傳。php 尚未配置為多個圖像文件,但這是一個開始。

我使用$_SESSION['file_n_desc']將描述保存到數據庫中。 我只需要弄清楚如何將糟糕的圖像上傳到文件夾,然后將位置保存到數據庫中。

我還需要將圖像重命名為隨機字符串(以防止圖像被覆蓋)。 我知道我可以用rand() function 做到這一點。

1) 上傳文件

當對文件輸入使用數組語法時,文件索引是最后一個鍵。 例如, $_FILES["file"]["name"]是一個文件名數組。 要獲取第 i 個文件的信息,您需要訪問$_FILES["file"]["name"][$i]$_FILES["file"]["size"][$i] &C。

2) 將圖像保存到文件夾

$_FILES中的某些數據(例如名稱)來自客戶端,因此不可信(即先驗證)。 對於文件名,您可以首先使用realpath來驗證目標文件路徑名是否安全,或者在組裝目標路徑名之前使用basenamepathinfo提取所提供名稱的最后一個組件。

3) 將圖像信息保存到數據庫

您提供的(不完整的)數據庫架構看起來就像您在同一個表中為每個圖像提供了兩列。 在關系 model 下,對多關系使用單獨的表建模:

CREATE TABLE images (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    `path` VARCHAR(256) NOT NULL,
    `description` TEXT,
    `member` INT UNSIGNED NOT NULL,
    FOREIGN KEY `member` REFERENCES members (`id`) ON DELETE CASCADE ON UPDATE CASCADE -- the image's owner
) Engine=InnoDB;

-- Note: this is a many-to-many relationship
CREATE TABLE ad_images (
    `ad` INT UNSIGNED NOT NULL,
    `image` INT UNSIGNED NOT NULL,
    FOREIGN KEY `ad` REFERENCES ads (`ad_id`) ON DELETE CASCADE ON UPDATE CASCADE,
    FOREIGN KEY `image` REFERENCES images (id) ON DELETE CASCADE ON UPDATE CASCADE,
    UNIQUE KEY (`ad`, `image`)
) Engine=InnoDB;

否則,當圖像數量少於最大數量時,您將打破零一無窮大規則並浪費空間。

其他

請注意,您可以對文件描述字段使用數組語法,以便更輕松地處理它們。 將它們命名為“filedesc[]”。

使用數組查找或模式匹配,而不是一長串的比較。

function isImage($type) {
    static $imageTypes = array(
            'image/gif'=>1, 'image/jpeg'=>1, 'image/pjpeg'=>1, 'image/png'=>1,
        );
    return isset($imageTypes[$type]);
    /* OR */
    return preg_match('%^image/(?:p?jpeg|gif|png)%', $type);
    /* OR allow all images */
    return preg_match('%^image/%', $type);
}

if (isImage($_FILES["file"]["type"][$idx]) && ($_FILES["file"]["size"][$idx] < 1048600)) {

文件類型是客戶端提供的值之一。 更安全的是使用fileinfo來獲取圖像類型。

$finfo = finfo_open(FILEINFO_MIME_TYPE);

if (isImage(finfo_file($finfo, $path)) && ($_FILES["file"]["size"][$idx] < 1048600)) {

如果文件具有有效的圖像 header 但 rest 無效,即使這樣也可能被愚弄。 您可以使用圖像庫(例如 GD 或 ImageMagick)通過檢查是否可以成功將文件作為圖像打開來驗證文件。

不確定您遇到了什么錯誤,因為您似乎對這個過程很清楚。 我第一次這樣做時,我以本教程為指導,一切正常: http://php.about.com/od/phpwithmysql/ss/Upload_file_sql.htm

我可以建議將文件存儲在數據庫中嗎? 這樣可以減少安全問題!

PS:我覺得你是一個初學者,我想我在PHP 新手:如何編寫好的代碼

2) 將圖像保存到指定的文件夾

move-uploaded-file應該可以工作。 想到的是您沒有設置正確的寫入權限來移動文件。 您使用哪種服務器(Linux/Windows/MacOSX)? function 作為布爾值(結果)返回什么?

另一件事:我需要將圖像重命名為隨機字符串(以防止圖像被覆蓋)。 我知道我可以用 rand() function 來做到這一點,但我忘了在我原來的帖子中提到它。

rand()並不是真正隨機的,並且可能會給出重復的文件名。 uniqid將是唯一的

編輯:我想出使用 $_SESSION['file_n_desc'] 將描述保存到數據庫中。 我只需要弄清楚如何上傳這些該死的東西,然后將位置保存到數據庫中。

當您沒有覆蓋 session 時使用 session 時,您使用的不是 MySQL 數據庫,而是文件系統 您可以閱讀本教程以在數據庫中存儲 session 標准的 session 在關閉瀏覽器時被清除(僅針對該會話)。 試試這個代碼:

<?php

session_start();

echo "<p>";
if (isset($_SESSION['count'])) {
    echo $_SESSION['count']++;
} else {
    $_SESSION['count'] = 0;
    echo $_SESSION['count']++;
}
echo "</p>";

echo "<p>" . session_id() . "</p>";

在不關閉瀏覽器的情況下加載該頁面幾次。 您將得到如下所示的內容:

0

rlu10shi6l390il130qinlt913


1

rlu10shi6l390il130qinlt913

但是當您關閉瀏覽器時,session_id 已更改並且您的計數器已重置,並且您會看到 output 看起來像。

0

fiakdijmmk38i40f39fm8u5mi4

1

fiakdijmmk38i40f39fm8u5mi4

能夠以畫廊設置的形式調用其分類列表中的圖像和描述

我使用PDO (Good Read)來執行(My)SQL。 我使用phpunit進行了單元測試(TDD)。 為了訪問數據庫,我在 memory 模式下使用了 SQLite(非常適合進行 SQL 測試)=> new PDO('sqlite::memory:'); . 我試圖遵循鮑勃叔叔的三個規則(Good Read)。

通常,您將其拆分為多個文件。 每個 class 在一個單獨的文件中。 每個 class 都應在單獨的文件中進行隔離(松散耦合)測試。

我使用了 map “Listing to Image”的外鍵 我認為這個例子經過了相當徹底的測試,但現在我真的該睡覺了,所以我不確定;)。

<?php

function createDatabase() {
    $db = new PDO('sqlite::memory:');
    $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    return $db;
}

function createTables($db) {

// Listing table containing all listings.
    $db->exec(
<<<EOT
CREATE TABLE IF NOT EXISTS listing(
id INTEGER PRIMARY KEY, 
description TEXT NOT NULL UNIQUE)
EOT
    );

// Image table containg all images.
    $db->exec(
<<<EOT
CREATE TABLE IF NOT EXISTS image(
id INTEGER PRIMARY KEY, 
listing_id INTEGER,
URL TEXT NOT NULL UNIQUE,
description TEXT NOT NULL UNIQUE,
FOREIGN KEY (listing_id) REFERENCES listing(id))
EOT
    );
}

class Listing {
    private $db;
    private $id;
    public $description;

    /*private function __construct() {

    }*/

    private function __construct(PDO $db, $id, $description) {
        $this->db = $db;
        $this->id = $id;
        $this->description = $description;
    }

    public static function create(PDO $db, $description) {
        $stmt = $db->prepare(<<<EOT
INSERT OR IGNORE INTO listing(description)
VALUES (:description)
EOT
        );
        $stmt->execute(array(
            ":description" => $description
        ));

        if ($stmt->rowCount() !== 1) {
            return NULL;
        }

        return new Listing($db, $db->lastInsertId(), $description);
    }

    public static function get(PDO $db, $id) {
        $stmt       = $db->prepare("SELECT description FROM listing WHERE id = :id");
        $stmt->execute(array(
            ":id" => $id
        ));
        $row = $stmt->fetch();

        if ($row == null) {
            return null;
        }
        return new Listing($db, $id, $row['description']);
    }

    public function getImages() {
        return Image::getImages($this->db, $this);
    }

    public function save() {
            $stmt = $this->db->prepare(
<<<EOT
UPDATE listing SET description = :description WHERE id = :id
EOT
            );
            $stmt->execute(array(
                ":description"  => $this->description,
                ":id"           => $this->id
            ));
    }

    public function id() {
        return $this->id;
    }
}

class Image {
    private $pdo;
    public $URL;
    private $id;
    public $description;

    private function __construct(PDO $pdo, $URL, $description, Listing $listing, $id) {
        $this->pdo          = $pdo;
        $this->URL          = $URL;
        $this->description  = $description;
        $this->id           = $id;
    }

    public static function create(PDO $pdo, $URL, $description, Listing $listing) {
        $stmt = $pdo->prepare(
<<<EOT
INSERT OR IGNORE INTO image(URL, listing_id, description)
VALUES (:URL, :listing_id, :description)
EOT
        );

        $stmt->execute(array(
            ":URL"          => $URL,
            ":listing_id"   => $listing->id(),
            ":description"  => $description
        ));

        if ($stmt->rowCount() !== 1) {
            return NULL;
        }

        return new Image($pdo, $URL, $description, $listing, $pdo->lastInsertId());
    }

    public function id() {
        return $this->id;
    }

    public static function getImages(PDO $pdo, Listing $listing) {
        $result = array();

        $stmt = $pdo->prepare(
<<<EOT
SELECT * FROM image where listing_id = :listing_id
EOT
        );

        $stmt->execute(array(
            ":listing_id"   => $listing->id(),
        ));

        while($row = $stmt->fetch()) {
            //$result[] = array($row['URL'], $row['description']);
            $result[] = new Image($pdo, $row['URL'], $row['description'], $listing, $row['id']);
        }  

        return $result;
    }
}

class Test extends PHPUnit_Framework_TestCase {
    protected $db;

    protected function setUp() {
        $this->db = createDatabase();
        createTables($this->db);
    }

    public function testCreatingSingleListing() {
        $listing1 = Listing::create($this->db, "Listing 1");   
        $this->assertEquals(1, $listing1->id());
    }


    public function testCreatingMultipleListings() {
        $listing1 = Listing::create($this->db, "Listing 1");
        $listing1 = Listing::create($this->db, "Listing 2");   
        $this->assertEquals(2, $listing1->id());
    }

    public function testReturningListingReturnsNullWhenNonexistence() {
        $this->assertNull(Listing::get($this->db, 1));
    }

    public function testReturningCreatedListing() {
        $Listing1 = Listing::create($this->db, "Listing 1");   
        $this->assertEquals("Listing 1", Listing::get($this->db, 1)->description);
    }

    public function testSavingListing() {
        $listing1 = Listing::create($this->db, "Listing 1");
        $listing1->description = "new";
        $listing1->save();
        $this->assertEquals("new", Listing::get($this->db, 1)->description);
    }

    public function testListingHasNoImagesWhenJustCreated() {
        $listing1 = Listing::create($this->db, "Listing 1");
        $this->assertEquals(array(), $listing1->getImages());
    }

    public function testAddingImageToListing() {
        $listing1 = Listing::create($this->db, "Listing 1");
        $image1 = Image::create($this->db, "http://localhost:12343/dfdfx/45.png", "first image", $listing1); 
        $this->assertEquals(array($image1), $listing1->getImages());
    }

    public function testAddingImagesToListing() {
        $listing1 = Listing::create($this->db, "Listing 1");
        $image1 = Image::create($this->db, "http://localhost:12343/dfdfx/45.png", "first image", $listing1);
        $image2 = Image::create($this->db, "http://localhost:12343/df/46.png", "second image", $listing1);
        $this->assertEquals(array($image1, $image2), $listing1->getImages());
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM