MiK*_*eko 5 php sql-server pdo sql-server-2014 php-7
背景
开发环境:
在Windows 10 x64上使用Apache 2.4.16的PHP 7.0.3
SQL Server 2014标准版
服务器在相应的文件列上启用了FileStream.
试图安装sqlsvr驱动程序但由于缺乏对PHP7的支持而失败
使用驱动程序从ODBC访问SQL Server SQL Server
PHP代码将图像数据插入MSSQL
$link = @new \PDO("odbc:Driver={SQL Server};Server=$server;Database=$db", $user, $password);
$stmt = $link->prepare("INSERT INTO [Attachment] (AttID, Seq , ModuleCde, AppID, StaffID , FileName , [File]) VALUES ( NEWID() , ? , ? , ? , ? , ? , ? )");
$stmt->bindValue(1,$_POST["Seq"],PDO::PARAM_INT);
$stmt->bindValue(2,$_POST["ModuleCde"],PDO::PARAM_STR);
$stmt->bindValue(3,$_POST["AppID"],PDO::PARAM_STR);
$stmt->bindValue(4,$_SESSION["StaffID"],PDO::PARAM_STR);
$stmt->bindValue(5,$_FILES["file"]["name"][$_POST["Seq"]],PDO::PARAM_STR);
$stmt->bindValue(6,file_get_contents($_FILES["file"]["tmp_name"][$_POST["Seq"]]),PDO::PARAM_STR);
$stmt->execute();
Run Code Online (Sandbox Code Playgroud)
PHP代码从MSSQL保存图像数据
$link = @new \PDO("odbc:Driver={SQL Server};Server=$server;Database=$db", $user, $password);
$stmt = $link->prepare("SELECT DATALENGTH([File]) AS [Size] , CONVERT(NVARCHAR(MAX),[File],2) AS [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?");
$stmt->bindValue(1,$_GET["ModuleCde"],PDO::PARAM_STR);
$stmt->bindValue(2,$_GET["AppID"],PDO::PARAM_STR);
$stmt->bindValue(3,$_GET["Seq"],PDO::PARAM_STR);
$stmt->bindValue(4,$_SESSION["StaffID"],PDO::PARAM_STR);
$stmt->execute();
$stmt->bindColumn(2,$img,PDO::PARAM_LOB, 0);
$stmt->fetch(PDO::FETCH_ASSOC);
file_put_contents( "file" , $img );
Run Code Online (Sandbox Code Playgroud)
该文件已成功上载到SQL服务器.打开DATASQL Server 的目录,所有上传的文件都可以通过Paint打开.
但是从上面的图像保存代码中获取的文件已损坏.该文件缺少原始文件中的一些字节.
尝试了方法
fwrite( fopen("file","w+") , strtolower("0x".str_replace("\0","",$img)) );
Run Code Online (Sandbox Code Playgroud)
以及此链接中说明的方法.
带有MSSQL的Php显示来自varbinary字段的原始数据
但两者都没有运气,文件似乎也被破坏了.
任何帮助表示赞赏.
编辑2016-02-25
修改SQL语句如下,但输出文件仍然已损坏.
$link->prepare("SELECT DATALENGTH([File]) AS [Size] , [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?");
Run Code Online (Sandbox Code Playgroud)
我现在正在尝试更改不同的SQL Server ODBC驱动程序,以查看该文件是否可以成功输出.
编辑2016-08-09
使用更新的PHP 7 MSSQL PDO驱动程序.一切都有魅力.
现在,我们不再需要convert使用这个新驱动程序的varbinary数据了.
当插入包含varbinary的表时,数据类型的选择对于PHP PDO来说非常重要。
PDO::PARAM_LOB应用于代替用于PDO::PARAM_STR文件列
为了确保 DB 通过驱动程序输出正确的文件,VARBINARY(MAX)通常使用此方法将字段转换为十六进制字符串并将其交给 PHPCONVERT(VARCHAR(MAX),[FileColumn],2)
将列转换为VARCHAR(MAX)而不是NVARCHAR(MAX)因为十六进制字符串不需要任何 Unicode 支持并保留纯十六进制字符串。
然后,十六进制字符串可以通过 PHP 函数有效地从十六进制数据转换回二进制hex2bin()。
解决方案
$link = @new \PDO("odbc:Driver={SQL Server};Server=$server;Database=$db", $user, $password);
$stmt = $link->prepare("SELECT DATALENGTH([File]) AS [Size] , CONVERT(VARCHAR(MAX),[File],2) AS [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?");
$stmt->bindValue(1,$_GET["ModuleCde"],PDO::PARAM_STR);
$stmt->bindValue(2,$_GET["AppID"],PDO::PARAM_STR);
$stmt->bindValue(3,$_GET["Seq"],PDO::PARAM_STR);
$stmt->bindValue(4,$_SESSION["StaffID"],PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
file_put_contents( "file" , hex2bin($result["File"]) );
Run Code Online (Sandbox Code Playgroud)
附加信息
SQL Server Native Client 11.0当从和中选择 varbinary 列时ODBC Driver 11 for SQL Server,既不将该列转换为varchar也不转换该列,PHP 会输出损坏的二进制结果,这是不需要的。但是SQL Server当我将列转换为VARCHAR(MAX). 我怀疑此操作是一个错误或驱动程序问题。
| 归档时间: |
|
| 查看次数: |
2339 次 |
| 最近记录: |