Quantcast
Channel: kristofdba – kristof dba
Viewing all articles
Browse latest Browse all 26

Filestream and powershell

$
0
0

I was looking for a way to store and retrieve FILES (pdf, xls, docx, jpg, png etc. …) in and from a SQL database using the FileStream option. Since bits are documented on the web but i did not find any straight forward solution i decided to write this post… I used stuff from COdeproject, the Msdn website and Sev17. Links bellow !

You should be able to work with Powershell, SQL Server Management studio and windows in general….
I stripped the noise and this is what is left:

Prepare your DB server (sql 2008 or higher) to use filestream:

On the DB server, run the SQL SERVER CONFIGURFileStroeATION MANAGER.
Find your Sql server service and select properties. Look for the FILESTREAM tab and select al options.
SQLSERVERPROPERTIES

Restart the service (Make sure nobody is connected… :) )

OKay… now , open up SQL server management studio, we’ll create a database now.
Thigs to now( you can choose your own but you’ll need to adapt them in all the code bits ! :
Your database name: FileStream
the Name of the FileGroup (yup, its a separate filegroup in SQL): FGFileStream
A path for the filegroup: e:\sql\FileStreamData
TableName: FileStore
Column Definitions.. youl find them bellow …

Ok. Lets create the DB (check your file paths ! )


CREATE DATABASE [FileStream]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'FileStream', FILENAME = N'F:\MSSQL11.MSSQLSERVER\MSSQL\Data\FileStream.mdf' , SIZE = 5120KB , FILEGROWTH = 1024KB ),
FILEGROUP [FGFileStream] CONTAINS FILESTREAM
( NAME = N'FileStreamData', FILENAME = N'E:\SQL\FileStreamData\FileStreamData' )
LOG ON
( NAME = N'FileStream_log', FILENAME = N'G:\MSSQL11.MSSQLSERVER\MSSQL\Data\FileStream_log.ldf' , SIZE = 1024KB , FILEGROWTH = 10%)
GO
USE [FileStream]
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTER DATABASE [FileStream] MODIFY FILEGROUP [PRIMARY] DEFAULT
GO
USE [FileStream]
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'FGFileStream') ALTER DATABASE [FileStream] MODIFY FILEGROUP [FGFileStream] DEFAULT
GO

Voila, now we’ll create our FileStore table.


Use FileStream
Go
CREATE TABLE dbo.FileStore
(
PkId int Primary Key IDENTITY (1, 1),
Id uniqueidentifier NOT NULL Unique ROWGUIDCOL Default newid(),
Description nvarchar(64) NOT NULL,
FileSummary varbinary(MAX),
FileData varbinary(MAX) FileStream NULL
)

Now lets insert some data. First , take a PDF document from your pc and put it on the database servers harddrive. EG :e:\data\placebo.pdf


INSERT INTO [FileStore] (Description, FileData)
Values( 'Placebo Ticket.PDF',(
SELECT * FROM
OPENROWSET(BULK N'e:\data\placebo.Pdf' ,SINGLE_BLOB)
AS Document
))

Now you should have your PDF stored on your file system accessible via Sql!

Let query the DB and see how it looks in pure t-sql. I’l cast the file data as varchar(max) so you can see the binary info..


SELECT [PkId],[Id],[Description],[FileData],CAST([FileData]
as varchar(Max)) FROM [FileStore]

This tells you … nothing. The data is in binary format so you’ll need to write it back to a file before you can do anything with it….
Just open up powershell and do this (Replace DirpAth with your own drive… and $server with your database server.):


$server = "Databaseserver"
$database = "FileStream"
$query = "SELECT Filedata, description FROM DBO.FileStore where description ='Placebo ticket.pdf'"
$dirPath = "e:"
$connection=new-object System.Data.SqlClient.SQLConnection
$connection.ConnectionString="Server={0};Database={1};Integrated Security=True" -f $server,$database
$command=new-object system.Data.SqlClient.SqlCommand($query,$connection)
$command.CommandTimeout=120
$connection.Open()
$reader = $command.ExecuteReader()
while ($reader.Read())
{
$sqlBytes = $reader.GetSqlBytes(0)
$filepath = "$dirPath{0}" -f $reader.GetValue(1)
$buffer = new-object byte[] -ArgumentList $reader.GetBytes(0,0,$null,0,$sqlBytes.Length)
$reader.GetBytes(0,0,$buffer,0,$buffer.Length)
$fs = new-object System.IO.FileStream($filePath,[System.IO.FileMode]'Create',[System.IO.FileAccess]'Write')
$fs.Write($buffer, 0, $buffer.Length)
$fs.Close()
}
$reader.Close()
$connection.Close()

Et voila!

This solution is fare from finished. I want to build something that takes a folder (or set of folder) and writes them to the DB (and FS , using filestream) and and interface to retrieve documents; Preferably as a VBA plugin for office…. but hey. the concept has been proven ! :)

Sources:

http://www.codeproject.com/Articles/128657/How-Do-I-Use-SQL-File-Stream

http://gaurangpatel.net/storing-files-in-sql-server-using-filestream

http://sev17.com/2010/05/11/t-sql-tuesday-006-blobs-filestream-and-powershell/

http://sqlcat.com/sqlcat/b/whitepapers/archive/2011/02/22/filestream-design-and-implementation-considerations.aspx



Viewing all articles
Browse latest Browse all 26

Trending Articles