【问题标题】:Using PHP to upload images to a folder while saving descriptions to a database使用 PHP 将图像上传到文件夹,同时将描述保存到数据库
【发布时间】:2011-10-05 09:48:07
【问题描述】:

用户决定为其分类列表上传多张图片。我需要做的是:

  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";
  }
?>

我知道我的 upload.php 尚未配置为多个图像文件,但这是一个开始。

我使用$_SESSION['file_n_desc'] 将描述保存到数据库中。我只需要弄清楚如何将糟糕的图像上传到文件夹,然后将位置保存到数据库中。

我还需要将图像重命名为随机字符串(以防止图像被覆盖)。我知道我可以使用 rand() 函数来做到这一点。

【问题讨论】:

  • 您遇到了哪些问题?上传/保存,mysql,还有什么?
  • 您的 4 个步骤几乎完成了该过程,上传 - 保存,将图像信息添加到 mysql,选择列表中的图像等等。你已经有什么代码了?
  • @Ryan Matthews:我可以将图像上传到文件夹中,但是将照片和描述保存在一起时有些头疼。
  • @Mark Hatting - 请分享您已经拥有的代码,以便我们知道从哪里开始提供帮助,否则我的猜测是您运行的进程太多并且可能顺序错误,这将停止图像name/id 从被链接到数据库中的数据,但这只是一个猜测,因为我看不到你的代码
  • 使用前端代码和处理器文件编辑了我的原始问题。

标签: php mysql upload


【解决方案1】:

1) 上传文件

当对文件输入使用数组语法时,文件索引是最后一个键。例如,$_FILES["file"]["name"] 是一个文件名数组。要获取第 i 个文件的信息,您需要访问 $_FILES["file"]["name"][$i]$_FILES["file"]["size"][$i] 等。

2) 将图像保存到文件夹

$_FILES 中的某些数据(如姓名)来自客户端,因此不可信(即先验证)。对于file name,您可以首先使用realpath 来验证目标文件路径名是否安全,或者使用basenamepathinfo 在组装目标路径名之前提取所提供名称的最后一个组件。

3) 将图像信息保存到数据库

您提供的(不完整的)数据库架构看起来就像您在同一个表中为每个图像提供了两列。在关系模型下,对多关系使用单独的表进行建模:

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;

否则,当图像数量少于最大数量时,您将违反 zero-one-infinity 规则并浪费空间。

其他

请注意,您可以对文件描述字段使用数组语法,以便更轻松地处理它们。将它们命名为“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)) {

如果文件有一个有效的图像标题,但其余部分无效,即使这样也可能被愚弄。您可以使用image library(例如 GD 或 ImageMagick)通过检查是否可以成功将文件作为图像打开来验证文件。

【讨论】:

    【解决方案2】:

    P.S:我感觉你是个初学者,我想我在PHP Newbies: How to write good code 列出了一个不错的列表

    2) 将图像保存到指定的文件夹

    move-uploaded-file 应该可以工作。想到的是您没有设置正确的写入权限来移动文件。您使用哪种服务器(Linux/Windows/MacOSX)?函数以 boolean(result) 形式返回什么?

    另一件事:我需要将图像重命名为随机字符串 (以防止图像被覆盖)。我知道我可以用 rand() 函数,但我忘了在我的原始帖子中提到它。

    rand() 不是真正随机的,可能会给出重复的文件名。 uniqid 将是唯一的

    编辑:我想办法将描述保存到数据库中 $_SESSION['file_n_desc']。我只需要弄清楚如何上传 该死的东西,然后将位置保存到数据库中。

    在没有覆盖会话的情况下使用会话时,您使用的不是 MySQL 数据库,而是the file-system。您可以阅读本教程以获取 store session in a database。标准此会话gets purged when closing the browser(仅用于该会话)。试试这个代码:

    <?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 已更改并且您的计数器已重置,并且您会得到类似的输出。

    0
    
    fiakdijmmk38i40f39fm8u5mi4
    

    1
    
    fiakdijmmk38i40f39fm8u5mi4
    

    能够调用其分类中的图像和描述 以画廊设置的形式列出

    我用PDO(Good Read) 来做(My)SQL。我使用phpunit 进行了单元测试(TDD)。为了访问数据库,我在内存模式下使用了 SQLite(非常适合进行 SQL 测试)=> new PDO('sqlite::memory:');。我尝试关注Uncle Bob's three rules(Good Read)。

    通常您将其拆分为多个文件。每个类都在一个单独的文件中。每个类都应该在单独的文件中进行隔离(松散耦合)测试。

    我使用foreign key 来映射“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());
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      不确定您遇到了什么错误,因为您似乎很清楚该过程。我第一次这样做时,我以本教程为指导,一切都很好:http://php.about.com/od/phpwithmysql/ss/Upload_file_sql.htm

      我可以建议将文件存储在数据库中吗?这样可以减少安全问题!

      【讨论】:

      猜你喜欢
      • 2014-02-25
      • 1970-01-01
      • 1970-01-01
      • 2021-09-29
      • 1970-01-01
      • 1970-01-01
      • 2018-04-01
      • 2011-04-21
      • 2015-09-18
      相关资源
      最近更新 更多