【问题标题】:Saving Files as blob in database ajax php pdo在数据库ajax​​ php pdo中将文件保存为blob
【发布时间】:2015-06-19 18:21:42
【问题描述】:
$fileCount = count($_FILES);
for ($i = 0; $i < $fileCount; $i++) {
    $fp = fopen($_FILES["file_".$i]['tmp_name'], 'rb');
    $stmt4 = $dbh - > prepare("INSERT INTO files_tbl (pin,remarks,fileblob,file_type,nameoffile,filesize) VALUES (?,?,?,?,?,?)");
    $stmt4 - > bindValue(1, $pin, PDO::PARAM_STR);
    $stmt4 - > bindValue(2, $remarks, PDO::PARAM_STR);
    $stmt4 - > bindParam(3, $fp, PDO::PARAM_LOB);
    $stmt4 - > bindParam(4, $_FILES["file_".$i]['type'], PDO::PARAM_STR);
    $stmt4 - > bindValue(5, $_FILES["file_".$i]['name'], PDO::PARAM_STR);
    $stmt4 - > bindValue(6, $_FILES["file_".$i]['size'], PDO::PARAM_STR);
    $stmt4 - > execute();
}

这就是我在 php 中将文件作为 blob 插入的方式。它正在保存文件,但没有正确保存。当我说它没有正确保存时,我的意思是在此过程中出现了问题。当我比较使用我的项目保存文件和在 XAMPP 中手动添加文件时,fileblob 存在差异,例如我在 xampp 中手动保存文件时,fileblob 为[BLOB - 488.9 KiB],当我使用项目时变为[BLOB - 479.2 KiB]。我认为这是我尝试从数据库显示文件时显示空白页的原因(当我显示的文件是我使用项目插入的文件时)但是如果我尝试显示的文件是我在 xampp 中手动插入的文件它正在显示文件。

我的插入可能有什么问题?为什么我没有保存正确的 blob

UPDATE

<input type="file" id="filecontent" name="filecontent" multiple="">

ajax

    var file = $('#filecontent')[0].files;
for (var i = 0; i < file.length; i++) {
    formData.append("file_" + i, file[i]);

    //more data are passed to formData
    //formData.append("file", file[i]);
    console.log(file[i]);
}

$.ajax({
    url: '../include/AddNew.php',
    type: 'POST',
    dataType: "json",
    data: formData,
    processData: false, // tell jQuery not to process the data
    contentType: false, // tell jQuery not to set contentType
    success: function(data) {
        console.log(data);
        alert(data.message);
        //window.location.reload(true);
    },
    error: function(data) {
        //alert("Error!"); // Optional
    }
});

UPDATE

当我尝试将print_r($_FILES); 放在for ($i = 0; $i &lt; $fileCount; $i++) { 行之前时,输出为

Array
(
    [file_0] => Array
        (
            [name] => whomovedmycheese - Copy.pdf
            [type] => application/pdf
            [tmp_name] => C:\Users\HogRider\xampp\tmp\phpE775.tmp
            [error] => 0
            [size] => 500624
        )

    [file_1] => Array
        (
            [name] => whomovedmycheese.pdf
            [type] => application/pdf
            [tmp_name] => C:\Users\HogRider\xampp\tmp\phpE786.tmp
            [error] => 0
            [size] => 500624
        )

)

UPDATE

【问题讨论】:

  • 能否贴出SQL命令的输出describe files_tbl;
  • 可能不相关,但你为什么混合bindParam()bindValue()?您还应该在循环之前只准备一次语句,如果您使用bindParam(),您也可以在循环之前执行此操作,这样您只需在循环中设置变量。
  • @jeroen 我只在 BLOB 上使用了参数,因为那是我在教程中看到的。我不知道这有什么并发症。我将重新制作代码并将其更改为值。在这个问题上马上回到你身边..
  • @RaphaelSchweikert 我更新了我保存表格的屏幕截图的问题
  • @HogRider 我想查看列类型。描述给你。

标签: php mysql ajax pdo blob


【解决方案1】:

你可以试试

MySQL

CREATE TABLE files (
    id   INT           AUTO_INCREMENT PRIMARY KEY,
    mime VARCHAR (255) NOT NULL,
    data BLOB          NOT NULL
);

PHP

  class BlobDemo {

        const DB_HOST = 'localhost';
        const DB_NAME = 'nameofdb';
        const DB_USER = 'username';
        const DB_PASSWORD = 'password';

        /**
         * PDO instance
         * @var PDO 
         */
        private $pdo = null;

        /**
         * Open the database connection
         */
        public function __construct() {
            // open database connection
            $conStr = sprintf("mysql:host=%s;dbname=%s;charset=utf8", self::DB_HOST, self::DB_NAME);

            try {
                $this->pdo = new PDO($conStr, self::DB_USER, self::DB_PASSWORD);
                //for prior PHP 5.3.6
                //$conn->exec("set names utf8");
            } catch (PDOException $e) {
                echo $e->getMessage();
            }
        }

        /**
         * insert blob into the files table
         * @param string $filePath
         * @param string $mime mimetype
         * @return bool
         */
        public function insertBlob($filePath, $mime) {
            $blob = fopen($filePath, 'rb');

            $sql = "INSERT INTO files(mime,data) VALUES(:mime,:data)";
            $stmt = $this->pdo->prepare($sql);

            $stmt->bindParam(':mime', $mime);
            $stmt->bindParam(':data', $blob, PDO::PARAM_LOB);

            return $stmt->execute();
        }
}

$blobObj = new BlobDemo();

// test insert pdf
$blobObj->insertBlob('pdf/prova.pdf',"application/pdf");

为我工作,我尝试使用 PDF、JPG 和 HTML 进行插入更新和查看。

【讨论】:

    【解决方案2】:

    根据PHP/PDO/MySQL: inserting into MEDIUMBLOB stores bad data,尝试使用以下行来构造您的 PDO 对象:

    $dbh = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES latin1 COLLATE latin1_general_ci"));
    

    说明

    我认为,正如 Ben M 在链接问题中指出的那样,这里有两个糟糕的设计决策。

    有一个连接字符集的概念。这个想法是 SQL 文本可以是任何字符集,然后在 SQL 服务器检索时进行转换。

    这不适用于二进制数据,因为它不是文本,因此,根据定义,不能在任何字符集中,但仍使用字符串文字进行传输

    这个问题可以通过在传输过程中引用 BLOB 数据来解决(使用 BASE64_* 函数或hex-escaping),事实上,很多人都在这样做。

    第二个设计决策是在 PDO/PHP 中:PDO 不进行任何字符集转换(它不能,因为 PHP 中的字符串本质上与字符集无关)所以 PHP 是唯一(或少数几种语言之一) SQL 传输字符集的选择实际上很重要,因为它需要匹配输入字符串实际所在的编码。

    在其他语言中,传输字符集只需要足够表达以包含可能在字符串中使用的任何字符。在当今的表情符号世界中,这很可能仅由 unicode 字符集(utf-8 等)保证。然而,这些都不是二进制安全的(因为不是每个可能的字节组合都会产生一个有效的字符串)所以即使我们可以解决 PHP 问题,我们仍然会遇到问题# 1.

    在理想情况下,SQL 命令在传输过程中总是在 ASCII 字符集中,并且每个字符串值都有一个字符集参数,其中“二进制”可能是一个可能的值,随它一起提供。 MySQL 实际上有这样一个字符串构造,它称之为“introducer”。然而,“_binary”似乎不是一个有效值。

    然后,另一端将使用此字符集信息将字符串值转换为其本机字符集(用于客户端到服务器传输的列或用于服务器到客户端传输的编程语言字符串字符集)。

    这样,在 BLOB 值中唯一需要转义的就是字符串分隔符("')。

    【讨论】:

    • 这是我的整个结构,也许这里有问题我仍然保存坏数据。 $dbh = new PDO("mysql:host=localhost", "root", "", array(PDO::MYSQL_ATTR_INIT_COMMAND =&gt; "SET NAMES latin1 COLLATE latin1_general_ci")); $dbh-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbname = "" .str_replace("", "``", $dbname) . ""; $dbh->query("CREATE DATABASE IF NOT EXISTS $dbname"); $dbh->query("SET CHARACTER SET utf8"); $dbh->query( "使用 $dbname");`
    • describe 输出似乎表明您的表格的文本字段是 latin1 字符集中的瑞典排序规则。以 UTF8 传输数据充其量是不必要的,或者在最坏的情况下是有害的,因为并非所有二进制数据都是有效的 UTF-8。
    • 你说得对,我评论了$dbh-&gt;query("SET CHARACTER SET utf8"); 部分,现在可以了。我能帮个忙吗,你能解释一下我想了解它是怎么发生的
    • @HogRider 我尽我所知修改了答案。
    猜你喜欢
    • 2015-05-06
    • 2018-11-12
    • 1970-01-01
    • 2019-09-15
    • 2012-04-28
    • 2017-08-21
    • 2016-11-04
    • 2011-02-14
    • 2011-04-01
    相关资源
    最近更新 更多