2016-02-24 20 views
5

nềnKhông thể tìm nạp dữ liệu varbinary từ MSSQL

môi trường phát triển:

PHP 7.0.3 với Apache 2.4.16 trên Windows 10 x64

SQL Server 2014 Chuẩn

Các sever đã bật FileStream trên các cột tệp tương ứng.

Cố gắng để cài đặt sqlsvr lái xe nhưng thất bại do thiếu sự hỗ trợ để PHP7

truy cập SQL server từ ODBC sử dụng driver SQL Server

PHP Code để chèn dữ liệu hình ảnh vào 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(); 

Mã PHP để lưu dữ liệu hình ảnh từ 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); 

Tệp được tải lên thành công tới máy chủ SQL. Mở thư mục DATA của SQL Server, tất cả các tệp đã tải lên và có thể được mở bằng Paint.

Nhưng việc tìm nạp tệp từ mã hình ảnh ở trên bị hỏng. Tệp thiếu một số byte từ tệp gốc.

Phương pháp thử

fwrite(fopen("file","w+") , strtolower("0x".str_replace("\0","",$img))); 

và cũng phương pháp được nêu trong liên kết này.

Php with MSSQL display raw data from varbinary field

Nhưng cả hai không có may mắn, tập tin dường như cũng bị hỏng.

Mọi trợ giúp đều được đánh giá cao.

Sửa 2016-02-25

Modified các câu lệnh SQL như sau nhưng file đầu ra vẫn bị hỏng.

$link->prepare("SELECT DATALENGTH([File]) AS [Size] , [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?"); 

Tôi hiện đang cố gắng thay đổi trình điều khiển ODBC máy chủ SQL khác nhau để xem tệp có thể xuất thành công hay không.

Sửa 2016-08-09

Với sự cập nhật MSSQL PDO driver cho PHP 7. Tất cả mọi thứ đã làm việc một lần nữa với một nét duyên dáng.

Bây giờ, chúng tôi không cần phải thêm convert dữ liệu varbinary nữa bằng trình điều khiển mới này.

Reference Link

Trả lời

4

Khi chèn vào các bảng chứa varbinary, chọn các kiểu dữ liệu là rất quan trọng đối với PHP PDO.

PDO::PARAM_LOB được sử dụng thay vì sử dụng PDO::PARAM_STR cho cột tập tin

Để đảm bảo DB có đầu ra tập tin chính xác thông qua các trình điều khiển, chuyển đổi lĩnh vực VARBINARY(MAX) vào chuỗi hex và bàn giao cho PHP thường sử dụng phương pháp này CONVERT(VARCHAR(MAX),[FileColumn],2)

Chuyển đổi cột thành VARCHAR(MAX) thay vì NVARCHAR(MAX) vì chuỗi HEX không cần bất kỳ hỗ trợ nào đối với Unicode và để lại chuỗi HEX đơn giản.

Sau đó, chuỗi thập lục phân có thể được chuyển đổi từ dữ liệu hex sang nhị phân thông qua hàm PHP hex2bin() một cách hiệu quả.

Giải pháp

$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"])); 

Thông tin bổ sung

Khi lựa chọn cột varbinary từ SQL Server Native Client 11.0ODBC Driver 11 for SQL Server, không phải chuyển đổi các cột để varchar hay không, PHP kết quả đầu ra là kết quả nhị phân hỏng mà là không mong muốn . Nhưng trình điều khiển SQL Server trả về thành công chuỗi HEX cho tôi khi tôi chuyển đổi cột thành VARCHAR(MAX). Tôi nghi ngờ hành động này là một lỗi hoặc một vấn đề trình điều khiển.

+0

Tôi sẽ khóc !! Tôi đã đấu tranh với dữ liệu php pdo và varbinary đến từ các máy chủ mssql ... Câu trả lời của bạn đã giúp rất nhiều !! Tôi có thể gửi một cái ôm điện tử không? : D Bây giờ ... Tôi có thể tìm hiểu thêm về điều này ở đâu? Tên của "kỹ thuật" này là gì? hoặc một cái gì đó như thế, vì vậy tôi có thể google nhiều hơn và có thêm kiến ​​thức – Frondor

+0

Tôi rất vui vì điều này sẽ giúp bạn. Đây không phải là một loại kỹ thuật, tôi chỉ nhận được giải pháp này bằng thử và sai. Kể từ khi tôi phát hiện ra rằng có một số báo cáo lỗi liên quan đến trình điều khiển php và ODBC chỉ ra rằng các trình điều khiển không xuất ra dữ liệu Unicode hợp lệ. Tôi sợ rằng dữ liệu 'varbinary' cũng sẽ được xử lý như Unicode vì vậy tôi đã cố gắng chuyển đổi nó thành chuỗi hex mà sẽ không được trình bày sai bởi trình điều khiển. Sau khi thử điều đó, tôi đã trả về thành công một chuỗi hex hợp lệ cho PHP. Sau đó, tôi chuyển đổi chuỗi chuỗi đó thành tệp. Đó là mẹo. – MiKeNeko

+0

Khi chúng tôi bị kẹt ở một loại dữ liệu, hãy thử xử lý nó/mã hóa nó để biến nó thành văn bản thuần túy. Đây là mẹo tôi đã làm. – MiKeNeko

3

Nếu bạn đang lưu trữ dữ liệu nhị phân không chuyển nó sang NVARCHAR() khi chọn nó - thử tháo CONVERT() từ này:

$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] = ?"); 

là thế này:

$stmt = $link->prepare("SELECT DATALENGTH([File]) AS [Size], [File] FROM [Attachment] WHERE [ModuleCde] = ? AND [AppID] = ? AND [Seq] = ? AND [StaffID] = ?"); 

Bạn cũng muốn đảm bảo cột của mình là VARBINARY(MAX).

Khi chèn dữ liệu của bạn tôi nghĩ rằng bạn cần phải sử dụng SQLSRV_ENCODING_BINARY (thay vì PDO::PARAM_STR)

+0

Cám ơn các bạn trả lời, như tôi không thể cài đặt 'sqlsvr' lái xe PDO vì vậy tôi sợ tôi không thể sử dụng 'SQLSRV_ENCODING_BINARY' – MiKeNeko

+0

@MiKeNeko, có' PDO :: PARAM_LOB' thể hữu ích hơn? Nó đưa ra các manh mối cho PDO và trình điều khiển cơ sở dữ liệu để xử lý dữ liệu khác nhau chứ không chỉ là các chuỗi. –

+0

@Ryan Vincent Cảm ơn bạn đã cho đầu mối của bạn, tôi thấy vấn đề là một vấn đề trình điều khiển SQL sever và vấn đề bây giờ là cố định. – MiKeNeko

-1
  1. Cài đặt MSSQL Server
  2. Cài đặt trình điều khiển ODBC theo hệ điều hành phiên bản và SQL Server phiên bản cũng ví dụ như 64 bit giành chiến thắng 10 và SQL server 12 yêu cầu lái xe odbc 11

    Tải từ liên kết này

  3. pdo_sqlsrv_.dll tải xuống tệp theo phiên bản php và dán vào thư mục php/ext và mở từ phần mở rộng php.ini porti trên. ví dụ: trong trường hợp của tôi, hãy cài đặt phiên bản xampp 3.2.2 bao gồm php 7.08, cho điều này tôi tải xuống pdo_sqlsrv_7_ts.dll và đặt theo như trên đề cập ở điểm 3.

    Tải từ liên kết này:

  4. Set thông số kết nối cơ sở dữ liệu trong file PHP như

    $ conn = new PDO ("sqlsrv: server = 127.0.0.1,1433; Database = test" , "", "");
    $ conn-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION);

Các vấn đề liên quan