当存储为blob时,微小的PNG大小膨胀

时间:2015-05-13 10:42:00

标签: php mysql blob

我有一个PHP脚本试图将图像作为blob存储到MySQL表中。该脚本运行正常,并按预期完成其工作。但是,当试图从表中查看存储的图像时,我注意到只有上半部分被存储;剩下的就是切断!这就是我的意思:

Original image Image retrieved from the blob

另外,我注意到图像大小在被存储为blob时没有明显的原因被填充。有问题的图像(左)最初是46kB,但是当从桌面(右)下载时,它显示36kB(我知道BLOB最多可以占用64kB,因此不应该成为问题)。这也发生在较小的图像上。

更有趣的是文件大小在PHPMyAdmin中看起来并不一致。看看:

这是表格视图: Table view

这是插入视图: Insert view

发生了什么?难道我做错了什么?如何将46kB文件在一个视图中变为36,在另一个视图中变为90?

至于我的 max_allowed_pa​​cket尺寸,它目前默认为4194304,远高于我试图存储的内容。

更新以下是将图片插入数据库的PHP代码段:

foreach($files as $fname) {
      if($fname != '.' && $fname != '..') {
          rename($oldfolder.$fname, $newfolder.$fname);
          $imgname = array_shift(explode(".",$fname)); //Individual image file name, without extension
          echo "\n".$imgname;
          $thumbph = fopen($newfolder.$fname, 'rb');
          $sql = 'UPDATE distilled_contacts SET THUMB = ? WHERE PHONE = ?';
          $connect = dbconn(PROJHOST,PROJDB,PROJDBUSER,PROJDBPWD);
          $query = $connect->prepare($sql);
          $query->bindParam(1, $thumbph, PDO::PARAM_LOB);
          $query->bindParam(2, $imgname);
          $query->execute();
          $query = NULL;
          $sql = NULL;
          $connect = NULL;
      }
  }

dbconn()函数如下所示:

function dbconn($strHost, $strDB, $strUser, $strPass) {
      try {
          $conn = new PDO("mysql:host=".$strHost.";dbname=".$strDB.";charset=utf8", $strUser, $strPass);
          $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
          $conn->setAttribute(PDO::ATTR_PERSISTENT, true);
          return $conn;
          }
      catch(PDOException $e) {
          die("Could not connect to the database $dbname :" . $e->getMessage());
          return false;
          }

  }

更新关于Ryan的请求,请参阅表格结构:

ID int(10) unsigned, auto-increment
PHONE varchar(20), utf8_unicode_ci
POPULARNAME varchar(60), utf8_unicode_ci
PREFERREDNAME varchar(60), utf8_unicode_ci
LATITUDE float(8,6)
LONGITUDE float(9,6)
LASTSEEN datetime
THUMB blob

数据库的默认排序规则是utf8_unicode_ci,我无法更改,因为我需要支持非欧洲语言。

PHP版本: 5.5.20, MySQL版本: 5.6.24

2 个答案:

答案 0 :(得分:1)

您在连接字符串中使用utf-8。这可能是问题吗?您可能必须将其删除并使用" SET NAMES utf8"。

请参阅:Is a BLOB converted using the current/default charset in MySQL?

另请参阅此处的评论:http://php.net/manual/en/pdo.lobs.php

具体来说:

  

我花了很多时间试图让它发挥作用,但不管我是什么   PDO是否损坏了我的数据。

     

我终于发现我一直在使用:

     

$ pdo-> exec(' SET CHARACTER SET utf8');

     

在我的连接脚本的TRY部分。

     

使用时将二进制输入提供给PDO时,此过程不起作用   参数lob。

<强>更新
喜欢这个

         function dbconn($strHost, $strDB, $strUser, $strPass) {
      try {
          $conn = new PDO("mysql:host=".$strHost.";dbname=".$strDB, $strUser, $strPass);
          $conn->exec('SET CHARACTER SET utf8');
          $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
          $conn->setAttribute(PDO::ATTR_PERSISTENT, true);
          return $conn;
          }
      catch(PDOException $e) {
          die("Could not connect to the database $dbname :" . $e->getMessage());
          return false;
          }
      }

答案 1 :(得分:1)

按照&#39;方法的要求&#39;确保&#39;上传&#39;和&#39;显示&#39;图像文件工作:

当&#39;事情&#39;变得混乱 - 我相信回到第一原则&#39;确保&#39;基础知识&#39;工作。

我的脚本工作&#39;这里有您的数据。我希望您确保这些脚本按预期工作。

我已将您的图片上传到&#39; blob&#39;正确的大小,并正确显示。

这些不是很漂亮的&#39; - 他们需要工作并且易于检查。

脚本:上传图片:

Q30212477_uploading-image.php

<?php  // Q30212477_uploading-image.php
  session_start();

  DEFINE ('BIGGEST_FILE', 64 * 1024);

/*
Table: distilled_contacts

Field        Type         Collation        Null    Key     Default  Extra           Privileges            Comment
-----------  -----------  ---------------  ------  ------  -------  --------------  --------------------  ---------
id           int(11)      (NULL)           NO      PRI     (NULL)   auto_increment  select,insert,update
PHONE        varchar(20)  utf8_general_ci  NO              (NULL)                   select,insert,update
POPULARNAME  varchar(60)  utf8_general_ci  NO              (NULL)                   select,insert,update
LATITUDE     float        (NULL)           NO              (NULL)                   select,insert,update
LONGITUDE    float        (NULL)           NO              (NULL)                   select,insert,update
THUMB        mediumblob   (NULL)           NO              (NULL)                   select,insert,update
*/
?>

<?php if (!empty($_FILES)): // process the form... ?>

<?php // process the input files...

// start file processing...
/* debug */ // var_dump($_FILES); // show what we got as files...

// database connection...
$dsn = 'mysql:host=localhost;dbname=testmysql';
$username = 'test';
$password = 'test';
$options = array(
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
);
$connection = new PDO($dsn, $username, $password, $options);
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

if (is_uploaded_file($_FILES['thumb']['tmp_name'])) {
   $imgThumb  = fopen($_FILES['thumb']['tmp_name'], 'rb');

   $stmt = $connection->prepare("INSERT INTO distilled_contacts (`PHONE`, `POPULARNAME`,
                                `LATITUDE`, `LONGITUDE`,
                                `THUMB`)
                                VALUES (?, ?, ?, ?, ?)");

   $stmt->bindValue(1, $_POST['phone'], PDO::PARAM_STR);
   $stmt->bindValue(2, $_POST['popularname'], PDO::PARAM_STR);
   $stmt->bindValue(3, $_POST['latitude'], PDO::PARAM_STR);
   $stmt->bindValue(4, $_POST['longitude'], PDO::PARAM_STR);
   $stmt->bindParam(5, $imgThumb, PDO::PARAM_LOB);

   $connection->beginTransaction();
   $stmt->execute();
   $connection->commit();

   fclose($imgThumb);
}
else
   echo "Error uploading image";

unset($connection);
?>
<?php endif; // processed the form? ?>

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Upload images</title>
  </head>

  <body>

    <form action="" method="POST" enctype="multipart/form-data">
      <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo BIGGEST_FILE ?>">

      <label for="phone">Phone Number</label>
      <input type="text" name="phone"  id="phone" value="1-800-TESTFILE"><br>

      <label for="popularname">Popular Name</label>
      <input type="text" name="popularname"  id="popularname" value="Jane Doe"><br>

      <label for="latitude">Latitude</label>
      <input type="text" name="latitude"  id="latitude" value="29.9792"><br>

      <label for="latitude">Longitude</label>
      <input type="text" name="longitude"  id="longitude" value="31.1344"><br>

      <label for="">Thumb image</label>
      <input type="file" name="thumb"  id="thumb" value="test_image_Q30212477.png"><br>

      <input type="submit" value="Upload file" />
    </form>
  </body>
</html>

<?php if (empty($_FILES)) {
  exit; // leave this script...
} ?>

并且:显示图片:

index.php - display image

<?php  // index.php

       // https://stackoverflow.com/questions/30212477/tiny-pngs-bloating-up-in-size-when-stored-as-blob#30212477

 // !!! Change this id for your record!!!
 $ID = '1';

// database connection...
$dsn = 'mysql:host=localhost;dbname=testmysql';
$username = 'test';
$password = 'test';
$options = array(
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
);
$connection = new PDO($dsn, $username, $password, $options);
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


// query
   $stmt = $connection->prepare("SELECT `PHONE`, `POPULARNAME`,
                                `LATITUDE`, `LONGITUDE`,
                                `THUMB`
                                FROM
                                    `distilled_contacts` dc
                                WHERE
                                    dc.id = ?");


   $result = array('PHONE' => "", 'POPULARNAME' => "",
                    'LATITUDE' => "", 'LONGITUDE' => "",
                    'THUMB' => null);


   $stmt->bindColumn(1, $result['PHONE']);
   $stmt->bindColumn(2, $result['POPULARNAME']);
   $stmt->bindColumn(3, $result['LATITUDE']);
   $stmt->bindColumn(4, $result['LONGITUDE']);
   $stmt->bindColumn(5, $result['THUMB']);

   // which row to return
   $stmt->bindValue(1, $ID);

   $allOK = $stmt->execute();

   // this returns an arry of results
   $allResults = $stmt->fetchAll(PDO::FETCH_ASSOC);

   /* debug */ // var_dump($result);

   $currentRow = current($allResults);
?>

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Upload images</title>
  </head>

  <body>
      <ul>
          <li>Phone: <?= $currentRow['PHONE'] ?></li>
          <li>Name: <?= $currentRow['POPULARNAME'] ?></li>
          <li>Lat:  <?= $currentRow['LATITUDE'] ?></li>
          <li>Long: <?= $currentRow['LONGITUDE'] ?><li>
          <li>
              <div style="border: red solid 1px;">
                 <img src="<?= 'data:image/'. 'png' .';base64,'. base64_encode($currentRow['THUMB']); ?>">
              </div>
          </li>
      </ul>


  </body>
</html>

您需要更改图片ID的$ID变量。