Сохранение файлов как blob в базе данных ajax php pdo

$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();
}

Вот как я вставляю файл как blob в php. Он сохраняет файл, но он не сохраняется должным образом. Когда я говорю, что это не экономит должным образом, я имею в виду, что на этом пути что-то не так. Когда я сравниваю сохранение файла с помощью моего проекта и вручную добавляя файл в XAMPP, есть разница в файловом блоке, например, я сохраняю файл вручную в 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 < $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

table

table

Ответы

Ответ 1

По PHP/PDO/MySQL: вставка в MEDIUMBLOB хранит плохие данные, попробуйте использовать следующую строку для создания вашего объекта PDO:

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

Объяснение

Я думаю, что есть, как отмечает Бен М в связанном вопросе, два плохих проектных решения на работе здесь.

Существует такая концепция кодировки соединения. Идея состоит в том, что текст SQL может быть в любой кодировке и затем преобразован при извлечении SQL-сервером.

Это не так хорошо работает с двоичными данными, поскольку это не текст и, следовательно, не должно по определению быть в любой кодировке, но все равно переносится с использованием строковых литералов.

Эта проблема может быть решена путем цитирования BLOB-данных во время передачи (либо с использованием функций BASE64_ *, либо посредством hex-escaping) и, действительно, это то, что делают многие люди.

Второе дизайнерское решение в PDO/PHP: PDO не делает никакого преобразования charset (это не возможно, потому что строки в PHP по своей сути являются чарсет-агностиками), поэтому PHP является единственным (или одним из немногих языков), где выбор кодировки передачи данных SQL действительно важна, поскольку она должна соответствовать кодировке, в которой фактически находятся входные строки.

В других языках кодировка передачи должна быть достаточно выразительной, чтобы охватывать любые символы, которые могут использоваться в строках. В сегодняшнем мире emojis это, скорее всего, гарантируется только кодировкой unicode (utf-8 и т.п.). Тем не менее, ни один из них не является двоично-безопасным (в том, что не всякая возможная комбинация байтов дает допустимую строку), поэтому, даже если мы могли бы обойти проблему с PHP, по-прежнему оставалась проблема № 1.

В идеальном мире команды SQL всегда будут в кодировке ASCII во время передачи, и каждое строковое значение будет иметь аргумент charset, из которого "двоичный" может быть возможным значением, поставляемым вместе с ним. MySQL фактически имеет такую ​​конструкцию для строк, которую он называет "интродуктором". "_binary", однако, не является допустимым значением.

Эта информация о кодировке затем будет использоваться другим концом для преобразования строкового значения в его собственную кодировку (либо столбцы для передачи между серверами, либо кодировку строк языков программирования для передачи между серверами).

Таким образом, единственное, что должно было бы быть экранировано в значениях BLOB, было бы ограничителем строк (" или ').

Ответ 2

Вы можете попробовать

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 для обновления и просмотра вставки.