Storing and Retrieving doc/pdf/xls files in SQL Server

advertisement
How To Store Any File into SQL Database
Introduction
This is just a simple article to store any file format into a SQL server database.
Background
Recently I completed a project where I need to store various files, i.e. Microsoft Office file
formats, PDF, Images, etc.). When I started writing code, I wrote a function to store binary, after
that I thought why not use direct bulk insert from a StoredProcedure.
Using the Code
I am going to discuss the ways in which you can directly store binary data into a SQL table by
using a simple stored procedure as given below:
Collapse
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:
Author,,Md. Marufuzzaman
-- Create date:
-- Description: Description,, Insert the Binary data
-- =============================================
-- EXEC dbo.spStoreBinaryFiles
'C:\eFaxFiles\eFaxPromo.pdf;D:\eFaxFiles\eFaxPromo.pdf;'
CREATE PROCEDURE [dbo].[spStoreBinaryFiles]
@FILE_PATH
VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @FILE_LENGTH BIGINT
DECLARE @FILE_DATA
VARBINARY(MAX)
DECLARE @FILE_NAME
VARCHAR(100)
DECLARE @DOCUMENT_NAME VARCHAR(100)
DECLARE @DOCUMENT_NATURE VARCHAR(5)
DECLARE @VAL1 VARCHAR(100)
DECLARE @VAL2 VARCHAR(100)
DECLARE curDOCUMENTS CURSOR FOR SELECT *
OPEN curDOCUMENTS
FETCH NEXT FROM curDOCUMENTS
INTO @VAL1,@VAL2
WHILE @@FETCH_STATUS = 0
BEGIN
FROM dbo.SPLIT ( ';', @FILE_PATH )
IF OBJECT_ID('#ORStable') IS NULL
BEGIN
CREATE TABLE #ORStable _
(Length BIGINT, vDocument VARBINARY(MAX))
DECLARE @SQL_QUERY
NVARCHAR(1000)
SET @SQL_QUERY= '
INSERT INTO #ORStable
SELECT len(bulkcolumn), *
FROM OPENROWSET(BULK '''+@VAL2+''', _
SINGLE_BLOB) AS BinaryData'
exec SP_executesql @SQL_QUERY
END
EXEC dbo.spGetDocumentNature @VAL2, @DOCUMENT_NATURE OUTPUT
EXEC dbo.spGetDocumentName @VAL2, @DOCUMENT_NAME OUTPUT
SELECT TOP 1 @FILE_LENGTH = Length, @FILE_DATA = vDocument FROM
#ORStable
INSERT INTO dbo.tblBinaryFiles
(
[File]
,[Path]
,[Ext]
,[Size]
,[Binary]
)
VALUES(
@DOCUMENT_NAME
,@VAL2
,@DOCUMENT_NATURE
,@FILE_LENGTH
,@FILE_DATA
)
DROP TABLE dbo.#ORStable
FETCH NEXT FROM curDOCUMENTS
INTO @VAL1,@VAL2
END
CLOSE curDOCUMENTS
DEALLOCATE curDOCUMENTS
END
OPENROWSET:
Includes all connection information necessary to access remote data from an OLE
DB data source. This method is an alternative to accessing tables in a linked server and is a onetime, ad hoc method of connecting and accessing remote data using OLE DB. The OPENROWSET
function can be referenced in the FROM clause of a query as though it is a table name. The
OPENROWSET
function can also be referenced as the target table of an INSERT, UPDATE, or DELETE
statement, subject to the capabilities of the OLE DB provider. Although the query may return
multiple result sets, OPENROWSET returns only the first one.
Binary Large Objects (BLOBs): BLOB data type to store any data that a program can generate:
graphic images, satellite images, video clips, audio clips, ...
BulkColumn:
The BulkColumn referenced in the query represents the varbinary value to be
inserted.
Sample Bulk Insert SQL Statement
Collapse
DECLARE @SQL_QUERY
NVARCHAR(1000)
SET @SQL_QUERY= '
INSERT INTO #ORStable
SELECT len(bulkcolumn), *
FROM OPENROWSET(BULK '''+@VAL2+''', _
SINGLE_BLOB) AS BinaryData'
exec SP_executesql @SQL_QUERY
--Here variable VAL2 contains the single file path information.
--Example VAL2 = "\\192.168.1.1\myFiles\myFile.pdf"
-VAL2 = "C:\myFiles\myFile.pdf"
Storing and Retrieving doc/pdf/xls files in SQL Server
August 31, 2007 by chiragrdarji
I have explained how to store and retrieve image file in SQL Server in my previous post. I
received many comments mentioning that how can we store and retrieve doc or pdf or excel (or
any type of file) in SQL Server. Few friends (developers) have also posted comment that they
receive only 13 byte when they retrieve stored image or doc or xls or pdf or rtf file. So I thought
let be write another blog for them. Sorry friends I am bit late in writing this article and mean
while you also have solved your issues. However this may help some new friends.
In this example I have used a table which has four fields. Below is the script for table,
CREATE TABLE [TestTable]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[FileName] [nvarchar](15) NOT NULL,
[Extension] [nvarchar](5) NOT NULL,
[Content] [image] NULL
)
Fig – (1) Scrpit for Table
In my demo project I have used one file Upload control (to upload the file),
one Textbox (where user can enter ID for uploaded file to retrieve it) and 2 buttons (one for
uploading file and other for retrieving).
When user select the file and click on Upload button the code stores the selected file in
database. Below is the code for that,
using (SqlConnection cnn = new SqlConnection(“Connection String”))
{
cnn.Open();
SqlCommand cmd = new SqlCommand(“InsertFile”, cnn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter(“@FileName”, “Name of
Uploaded File”));
cmd.Parameters.Add(new SqlParameter(“@Extension”, “Extension of
Uploaded File”));
cmd.Parameters.Add(new SqlParameter(“@Content”, “byte array
(byte[]) of uploaded file”));
cnn.Close()
}
Fig – (2) Code for inserting selected file in database.
Now when user enter FileID for uploaded file in textbox and click on retrieve button we
will get the Content and extension field from database for that file id. You can use FillDataSet
method to retrieve the byte array. Below code shows how to send retrieved file to user depending
on the extension.
string strExtenstion = “extension of retrieved file”;
byte[] bytFile = “Byte array retrieved from database”;
Response.Clear();
Response.Buffer = true;
if (strExtenstion == “.doc” || strExtenstion == “.docx”)
{
Response.ContentType = “application/vnd.ms-word”;
Response.AddHeader(“content-disposition”,
“attachment;filename=Tr.doc”);
}
else if (strExtenstion == “.xls” || strExtenstion == “.xlsx”)
{
Response.ContentType = “application/vnd.ms-excel”;
Response.AddHeader(“content-disposition”,
“attachment;filename=Tr.xls”);
}
else if (strExtenstion == “.pdf”)
{
Response.ContentType = “application/pdf”;
Response.AddHeader(“content-disposition”,
“attachment;filename=Tr.pdf”);
}
Response.Charset = “”;
Response.Cache.SetCacheability(HttpCacheability.NoCache);
// If you write,
// Response.Write(bytFile1);
// then you will get only 13 byte in bytFile.
Response.BinaryWrite(bytFile);
Response.End();
Fig – (3) Code to retrieve the file from database.
1. Happy Programming !!!
Get List Of Files From a Windows Directory to SQL Server
In SQL Server, we read data from single text file; excel file…etc. However we can extend this to
read all the files in a particular directory. This post demonstrates a part of this scenario. Here we
will discuss how to get the list of files from a particular directory, then can be extended to load
them into SQL Server, which is not the scope of this post.
So in order to use xp_cmdshell, we need to enable it as it is disabled by default.
Here is the way to enable:
--allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
--Update the currently configured value for advanced options.
RECONFIGURE
GO
--Enable XP_CMDSHELL
EXEC sp_configure 'xp_cmdshell', 1
GO
--Update the currently configured value for this feature.
RECONFIGURE
GO
Refer Image-1 for the list of files in the directory. Now create a table and load the file list into it:
--Create the table to store file list
CREATE TABLE myFileList (FileNumber INT IDENTITY,FileName VARCHAR(256))
--Insert file list from directory to SQL Server
DECLARE @Path varchar(256) = 'dir C:\Import\'
DECLARE @Command varchar(1024) = @Path + ' /A-D /B'
INSERT INTO myFileList
EXEC MASTER.dbo.xp_cmdshell @Command
--Check the list
SELECT * FROM myFileList
GO
--Clean up
DROP TABLE myFileList
GO
Here is the result in the table.
This can be extendable to other file operations too. Leave your valuable comments and sug
This tutorial shows you how to store raw binary data in a SQL Database using VB.NET
and ASP.NET 3.5
In this tutorial, we will be looking at how to upload and store binary data in a SQL database.
Probably the most popular way to store uploaded files is within the file system of the server, but
storing files in a database does have its advantages. Using a database to store the raw binary data
of files will help with backing up, as all the data is encapsulated within the database - no need to
worry about any files that the database will be linking to.
Using the SQL data type varbinary, we can store files upto 2GB in size. In this example, we will
create a simple upload form and demonstrate how to upload a GIF or JPEG and store it within
the database. Doing it this way, we will need to record the MIME data type of the uploaded file,
also, as it will be stored in raw binary form.
The first thing we should do is design our database. Let's create a table with the following
columns (and data types):
- ID (bigint);
- FileName (varchar(50));
- DateTimeUploaded (datetime);
- MIME (varchar(50));
- BinaryData (varbinary(MAX)).
Now we have our table designed, let's move on to creating our upload form. We will require a
textbox for the name of the file, a file upload control as well as a button:
<form id="form1" runat="server">
Please upload either a JPEG or a GIF:<br />
<asp:Literal ID="lit_Status" runat="server" /><br />
<b>Name:</b>
<asp:TextBox ID="FileName" runat="server" />
<br />
<b>File:</b>
<asp:FileUpload ID="FileToUpload" runat="server" />
<br />
<asp:Button ID="btn_Upload" runat="server" Text="Upload" />
</form>
We moved our web sites to Server Intellect and have found them to be incredibly professional.
Their setup is very easy and we were up and running in no time.
We will also use a Literal control to display status messages to the user.
Now we will need to connect to our database, so make sure we have our connection string in the
Web.config:
<connectionStrings>
<add name="ConnectionString" connectionString="Data
Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated
Security=True;User Instance=True" providerName="System.Data.SqlClient" />
</connectionStrings>
If you do not, a quick way to add the connection string is to drag a SqlDataSource control from
the toolbox onto the page and configure it using the Smart Tag in design view. This will set the
DataSource to the database we created earlier and input the connection string in the Web.config,
and once you are done configuring, you can simply delete the SqlDataSource.
Next up, we will create a handler for the Submit button. A quick way to do this is to enter design
view of the ASPX page and double-click the Submit button:
Imports System.Data.SqlClient
Imports System.IO
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub btn_Upload_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btn_Upload.Click
End Sub
End Class
I just signed up at Server Intellect and couldn't be more pleased with my Windows Server!
Check it out and see for yourself.
The first thing we want to do is to check if the file uploaded successfully:
If FileToUpload.PostedFile Is Nothing OrElse
String.IsNullOrEmpty(FileToUpload.PostedFile.FileName) OrElse
FileToUpload.PostedFile.InputStream Is Nothing Then
lit_Status.Text = "<br />Error - unable to upload file. Please try again.<br />"
Exit Sub
End If
If the file is not uploaded, or there is no file to upload, we want to tell the user and break out of
the Sub.
The next thing to do is to find out the file extension of the file:
Dim extension As String =
Path.GetExtension(FileToUpload.PostedFile.FileName).ToLower()
Dim fileType As String = Nothing
Select Case extension
Case ".gif"
fileType = "image/gif"
Case ".jpg", ".jpeg", ".jpe"
fileType = "image/jpeg"
Case ".png"
fileType = "image/png"
Case Else
lit_Status.Text = "<br />Error - invalid file type.<br />"
Exit Sub
End Select
Server Intellect assists companies of all sizes with their hosting needs by offering fully
configured server solutions coupled with proactive server management services. Server Intellect
specializes in providing complete internet-ready server solutions backed by their expert 24/365
proactive support team.
Finally, we use our connection to insert into the database:
Using Conn As New
SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
)
Try
Const SQL As String = "INSERT INTO [BinaryTable] ([FileName], [DateTimeUploaded],
[MIME], [BinaryData]) VALUES (@FileName, @DateTimeUploaded, @MIME,
@BinaryData)"
Dim cmd As New SqlCommand(SQL, Conn)
cmd.Parameters.AddWithValue("@FileName", FileName.Text.Trim())
cmd.Parameters.AddWithValue("@MIME", fileType)
Dim imageBytes(FileToUpload.PostedFile.InputStream.Length) As Byte
FileToUpload.PostedFile.InputStream.Read(imageBytes, 0, imageBytes.Length)
cmd.Parameters.AddWithValue("@BinaryData", imageBytes)
cmd.Parameters.AddWithValue("@DateTimeUploaded", DateTime.Now)
lit_Status.Text = "<br />File successfully uploaded - thank you.<br />"
Conn.Open()
cmd.ExecuteNonQuery()
Conn.Close()
Catch ex As Exception
Conn.Close()
End Try
End Using
We use a regular SQL Statement to insert the data into the database, and use SQL Parameters to
pass the data from our form to the database.
The entire code-behind looks like this:
Imports System.Data.SqlClient
Imports System.IO
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub btn_Upload_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Handles btn_Upload.Click
If FileToUpload.PostedFile Is Nothing OrElse
String.IsNullOrEmpty(FileToUpload.PostedFile.FileName) OrElse
FileToUpload.PostedFile.InputStream Is Nothing Then
lit_Status.Text = "<br />Error - unable to upload file. Please try again.<br />"
Exit Sub
End If
Dim extension As String = Path.GetExtension(FileToUpload.PostedFile.FileName).ToLower()
Dim fileType As String = Nothing
Select Case extension
Case ".gif"
fileType = "image/gif"
Case ".jpg", ".jpeg", ".jpe"
fileType = "image/jpeg"
Case ".png"
fileType = "image/png"
Case Else
lit_Status.Text = "<br />Error - invalid file type.<br />" Exit Sub
End Select
Using Conn As New
SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
)
Try
Const SQL As String = "INSERT INTO [BinaryTable] ([FileName], [DateTimeUploaded],
[MIME], [BinaryData]) VALUES (@FileName, @DateTimeUploaded, @MIME,
@BinaryData)"
Dim cmd As New SqlCommand(SQL, Conn)
cmd.Parameters.AddWithValue("@FileName", FileName.Text.Trim())
cmd.Parameters.AddWithValue("@MIME", fileType)
Dim imageBytes(FileToUpload.PostedFile.InputStream.Length) As Byte
FileToUpload.PostedFile.InputStream.Read(imageBytes, 0, imageBytes.Length)
cmd.Parameters.AddWithValue("@BinaryData", imageBytes)
cmd.Parameters.AddWithValue("@DateTimeUploaded", DateTime.Now)
lit_Status.Text = "<br />File successfully uploaded - thank you.<br />"
Conn.Open()
cmd.ExecuteNonQuery()
Conn.Close()
Catch ex As Exception
Conn.Close()
End Try
End Using
End Sub
End Class
Retrieving Binary Data from SQL Database with VB.NET
This tutorial shows you how to retrieve raw binary data from a SQL Database using
VB.NET and ASP.NET 3.5
In this tutorial, we will be following on from our earlier tutorial, Storing Binary Data in SQL
Database with VB.NET, and see how we can take it a step further and display the JPEG or GIF
image directly from the database.
We will be building upon the existing code in the earlier project, so if you want to go through
that tutorial first, the link is above. The only thing we need to add to the existing page is to
display a link to view the recently uploaded image. To do this, we will change the way we
execute the inserting of the file. Below is what we used in the first example:
Using Conn As New
SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
)
Try
Const SQL As String = "INSERT INTO [BinaryTable] ([FileName], [DateTimeUploaded],
[MIME], [BinaryData]) VALUES (@FileName, @DateTimeUploaded, @MIME,
@BinaryData)"
Dim cmd As New SqlCommand(SQL, Conn)
cmd.Parameters.AddWithValue("@FileName", FileName.Text.Trim())
cmd.Parameters.AddWithValue("@MIME", fileType)
Dim imageBytes(FileToUpload.PostedFile.InputStream.Length) As Byte
FileToUpload.PostedFile.InputStream.Read(imageBytes, 0, imageBytes.Length)
cmd.Parameters.AddWithValue("@BinaryData", imageBytes)
cmd.Parameters.AddWithValue("@DateTimeUploaded", DateTime.Now)
Conn.Open()
cmd.ExecuteNonQuery()
lit_Status.Text = "<br />File successfully uploaded - thank you.<br />"
Conn.Close()
Catch ex As Exception
Conn.Close()
End Try
End Using
I just signed up at Server Intellect and couldn't be more pleased with my Windows Server!
Check it out and see for yourself.
Instead of calling the ExecuteNonQuery method, we will call the ExecuteScalar method and
change the SQL statement to return the new ID that has just been inserted:
Using Conn As New
SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
)
Try
Const SQL As String = "INSERT INTO [BinaryTable] ([FileName], [DateTimeUploaded],
[MIME], [BinaryData]) VALUES (@FileName, @DateTimeUploaded, @MIME, @BinaryData)
SELECT SCOPE_IDENTITY()"
Dim cmd As New SqlCommand(SQL, Conn)
cmd.Parameters.AddWithValue("@FileName", FileName.Text.Trim())
cmd.Parameters.AddWithValue("@MIME", fileType)
Dim imageBytes(FileToUpload.PostedFile.InputStream.Length) As Byte
FileToUpload.PostedFile.InputStream.Read(imageBytes, 0, imageBytes.Length)
cmd.Parameters.AddWithValue("@BinaryData", imageBytes)
cmd.Parameters.AddWithValue("@DateTimeUploaded", DateTime.Now)
Conn.Open()
Dim theInt As Integer = Convert.ToInt32(cmd.ExecuteScalar())
lit_Status.Text = "<br />File successfully uploaded - thank you.<br />"
lnk_Picture.NavigateUrl = "~/ShowImage.aspx?ID=" & theInt.ToString()
Conn.Close()
Catch ex As Exception
Conn.Close()
End Try
End Using
We use the SQL Method SELECT SCOPE_IDENTITY() to return the ID of the record that has
just been inserted. We then utilize this ID with the ExecuteScalar method and put the ID into the
NavigateUrl of a HyperLink control we added to the form to utilize a querystring. Our form now
looks like this:
<form id="form1" runat="server">
Please upload either a JPEG or a GIF:<br />
<asp:Literal ID="lit_Status" runat="server" /><br />
<asp:HyperLink ID="lnk_Picture" runat="server" text="Click Here" />
<b>Name:</b>
<asp:TextBox ID="FileName" runat="server" />
<br />
<b>File:</b>
<asp:FileUpload ID="FileToUpload" runat="server" />
<br />
<asp:Button ID="btn_Upload" runat="server" Text="Upload" />
</form>
We migrated our web sites to Server Intellect over one weekend and the setup was so smooth
that we were up and running right away. They assisted us with everything we needed to do for all
of our applications. With Server Intellect's help, we were able to avoid any headaches!
Just the one change on the form - the addition of the HyperLink.
We are going to use a new page to display the image, so add a new WebForm to your project
named ShowImage.aspx
First, we need to add the following assembly reference for this new page:
Imports System.Data.SqlClient
Next, add the following to the Page Load event:
Try
Dim PictureID As Integer = Convert.ToInt32(Request.QueryString("ID"))
Using myConnection As New
SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
)
Const SQL As String = "SELECT [MIME], [BinaryData] FROM [BinaryTable] WHERE [ID] =
@ID"
Dim myCommand As New SqlCommand(SQL, myConnection)
myCommand.Parameters.AddWithValue("@ID", PictureID)
myConnection.Open()
Dim myReader As SqlDataReader = myCommand.ExecuteReader()
If myReader.Read Then
Response.ContentType = myReader("MIME").ToString()
Response.BinaryWrite(myReader("BinaryData"))
End If
myReader.Close()
myConnection.Close()
End Using
Catch ex As Exception
Response.Write(ex.ToString())
End Try
We chose Server Intellect for its dedicated servers, for our web hosting. They have managed to
handle virtually everything for us, from start to finish. And their customer service is stellar.
Here, we are simply using the querystring to locate the image in the database, and then
displaying it with the SqlDataReader and BinaryWrite.
The entire code-behind of the new page should look something like this:
Imports System.Data.SqlClient
Partial Class ShowImage
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Me.Load
Try
Dim PictureID As Integer = Convert.ToInt32(Request.QueryString("ID"))
Using myConnection As New
SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
)
Const SQL As String = "SELECT [MIME], [BinaryData] FROM [BinaryTable] WHERE [ID] =
@ID"
Dim myCommand As New SqlCommand(SQL, myConnection)
myCommand.Parameters.AddWithValue("@ID", PictureID)
myConnection.Open()
Dim myReader As SqlDataReader = myCommand.ExecuteReader()
If myReader.Read Then
Response.ContentType = myReader("MIME").ToString()
Response.BinaryWrite(myReader("BinaryData"))
End If
myReader.Close()
myConnection.Close()
End Using
Catch ex As Exception
Response.Write(ex.ToString())
End Try
End Sub
End Class
Download