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