Попытка извлечь данные из SQL-формы с помощью скрипта PS

#sql #sql-server #powershell

Вопрос:

Я пытался заставить скрипт PS работать при извлечении файлов (pdf, word и т.д.) Из базы данных SQL Server. Я наткнулся на приведенный ниже сценарий PowerShell. Сценарий запускается и заполняет папку назначения, но все файлы имеют размер 0 байт и во время выполнения сценария. Это приводит к ошибке:

«Экспорт объектов из контейнера FILESTREAM: Исключение .docx, вызывающее «getBytes» с аргументом(ами) «5»: «Недопустимая попытка получить байты в столбце «расширение». Функция getBytes может использоваться только для столбцов типа e Text, NText или изображения.»»

Может ли кто-нибудь указать мне, что я делаю не так и как это исправить, пожалуйста? Очень признателен.

 $Server = ".xxxxxx";             
$Database = "xxxxxx"; 
$Dest = "C:DATA";     
$bufferSize = 8192;       


$Sql = "
SELECT 
      [extension]
      
  FROM [XXXXXXXX].[dbo].[XXXXXXdocuments]
"; 
 
 
$con = New-Object Data.SqlClient.SqlConnection; 
$con.ConnectionString = "Data Source=$Server;"   
 "Integrated Security=True;"   
 "Initial Catalog=$Database"; 
$con.Open(); 

Write-Output ((Get-Date -format yyyy-MM-dd-HH:mm:ss)   ": Started ..."); 
 
 
$cmd = New-Object Data.SqlClient.SqlCommand $Sql, $con; 
$cmd.CommandTimeout = 120 
$rd = $cmd.ExecuteReader(); 
 
 
$out = [array]::CreateInstance('Byte', $bufferSize) 
 
 
While ($rd.Read()) 
{ 
 try 
  { 
   Write-Output ("Exporting Objects from FILESTREAM container: {0}" -f $rd.GetString(0)); 
 
   $fs = New-Object System.IO.FileStream ($Dest   $rd.GetString(0)), Create, Write; 
   $bw = New-Object System.IO.BinaryWriter $fs; 
 
   $start = 0; 
 

    enter code here

   $received = $rd.Getbytes(0, $start, $out, 0, $bufferSize - 1); 
   While ($received -gt 0) 
   { 
    $bw.Write($out, 0,      $received); 
    $bw.Flush(); 
    $start  = $received; 
 
    $received = $rd.Getbytes(0, $start, $out, 0, $bufferSize - 1); 
   } 
   $bw.Close(); 
   $fs.Close(); 
  } 
  catch 
  { 
   Write-Output ($_.Exception.Message) 
  } 
  finally 
  { 
   $fs.Dispose();         
  }
 }  
   
 
$rd.Close(); 
$cmd.Dispose(); 
$con.Close(); 
 
Write-Output ("Finished");
Read-Host -Prompt "Press Enter to exit"
 

Комментарии:

1. Ошибка кажется очевидной в отношении проблемы с данными, когда поле, которое вы пытаетесь прочитать, не может быть вызвано GetBytes() . Каков тип поля данных extension ? Помните varchar , что » или nvarchar «- это не то же text самое, что «или ntext «. Вы сохраняете двоичные данные PDF, DOCX и т.д. в базе данных?

2. Спасибо, что уделили время, чтобы посмотреть на это, мне удалось выяснить, что проблема в том, что я вызывал столбцы, которые не содержали данные, которые я пытался извлечь, после того, как они были просмотрены и исправлены, все работает нормально. Очень признателен

Ответ №1:

BinaryWriter не нужен. Это для записи примитивных типов в поток.

И нет необходимости возиться с буферами; вы можете просто использовать SqlDataReader.GetStream(int).CopyTo(Stream) , например

 $Server = "localhost";             
$Database = "adventureworks2017"; 
$Dest = "C:temp";     

$Sql = "
SELECT concat('photo', ProductPhotoID, '.jpg') name, LargePhoto from Production.ProductPhoto
"; 
 
 
$con = New-Object Data.SqlClient.SqlConnection; 
$con.ConnectionString = "Data Source=$Server;Integrated Security=True;Initial Catalog=$Database;TrustServerCertificate=true"; 
$con.Open(); 

Write-Output ((Get-Date -format yyyy-MM-dd-HH:mm:ss)   ": Started ..."); 
  
$cmd = New-Object Data.SqlClient.SqlCommand $Sql, $con; 
$cmd.CommandTimeout = 120 
$rd = $cmd.ExecuteReader(); 

 

While ($rd.Read()) 
{ 
 try 
  { 
   Write-Output ("Exporting: {0}" -f $rd.GetString(0)); 
 
   $fs = New-Object System.IO.FileStream ($Dest   $rd.GetString(0)), Create, Write; 
   $rd.GetStream(1).CopyTo($fs) 
   $fs.Close()
  } 
  catch 
  { 
   Write-Output ($_.Exception.Message) 
  } 
  finally 
  { 
   $fs.Dispose();         
  }
 }  
   
 
$rd.Close(); 
$cmd.Dispose(); 
$con.Close(); 
 
Write-Output ("Finished");