将文件保存为数据库中的 blob ajax php pdo
Saving Files as blob in database 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 中手动添加文件时,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 < $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
根据 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 等)保证。但是,其中 none 是二进制安全的 (因为并非所有可能的字节组合都会产生有效的字符串)所以即使我们可以解决 PHP问题,我们仍然会遇到问题 #1。
在理想情况下,SQL 命令在传输过程中始终位于 ASCII 字符集中,每个字符串值都有一个字符集参数,其中“二进制”可能是一个可能的值,随它一起提供。 MySQL 实际上有这样一个字符串构造,它称之为“introducer”。但是,“_binary”似乎不是有效值。
此字符集信息将被另一端用于将字符串值转换为其本机字符集(用于客户端到服务器传输的列或用于服务器到客户端传输的编程语言的字符串字符集) ).
这样,BLOB 值中唯一需要转义的就是字符串定界符("
或 '
)。
你可以试试
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 进行插入更新和查看。
$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 中手动添加文件时,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 < $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
根据 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 等)保证。但是,其中 none 是二进制安全的 (因为并非所有可能的字节组合都会产生有效的字符串)所以即使我们可以解决 PHP问题,我们仍然会遇到问题 #1。
在理想情况下,SQL 命令在传输过程中始终位于 ASCII 字符集中,每个字符串值都有一个字符集参数,其中“二进制”可能是一个可能的值,随它一起提供。 MySQL 实际上有这样一个字符串构造,它称之为“introducer”。但是,“_binary”似乎不是有效值。
此字符集信息将被另一端用于将字符串值转换为其本机字符集(用于客户端到服务器传输的列或用于服务器到客户端传输的编程语言的字符串字符集) ).
这样,BLOB 值中唯一需要转义的就是字符串定界符("
或 '
)。
你可以试试
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 进行插入更新和查看。