You are on page 1of 17

The Code Project - Uploading / Downloading Pictures to / from a SQL Server - C#

DatabaseView
our advertisersAdvertise with us
ASP.NET, All Topics, C#, .NET >> C# Database >> General
Uploading / Downloading Pictures to / from a SQL Server
By Alexandru Ghiondea
Describes how to upload and download pictures to and from a
SQL Server database. C#, SQL
Windows (WinXP), .NET (.NET 1.1)
Win32, SQL (SQL 2000), VS (VS.NET2003)
DB, Dev
Posted 29 Oct 2004 4:49
Articles by this author
18,413 views
Search: Articles Authors
Help!ArticlesMessage BoardsStoreFrontLounge

Toolbox
Broken Article?
VS.NET 2003 for $899
Ultimate Toolbox $499
Print version
Send to a friend

Sign in / Sign up
Email
Password
Remember me

Lost your Password?

15 members have rated this article. Result:


Popularity: 5.33. Rating: 4.53 out of 5.
Download demo project - 19 Kb
Download database script - 0.7 Kb

Introduction
In order to provide your application with cool pictures, you can employ
two techniques (at least). One of them is that you can save the pictures
in a folder and store the path to each one in a database or file. The
other one is to store the entire file into a database, along with its file
name.
Each of them has its ups and downs:
If you save your files to a folder, you might accidentally delete a file
from that folder. If this happens, you will end up with a broken link
in your database or configuration file. However, the hard disk storage
space is cheap, so you can afford to store a lot of files.
If you store your files into a database, you can enforce security by
using the security settings of the database. Also, there are no broken
links ever. However, the database storage space is more expensive.
Another idea is that you can save a thumbnail of the image on the database
for quick access and save the actual picture on hard drive.
Of course, each application has its particularities, and you have to
choose which one you will use.
OK. Enough of the philosophical talk! Let s dive into the good stuff.
The application
The problem of uploading files to a database is not that difficult. You
have to use, on the server, a certain data type when creating the table.
This data type has to be capable of storing large amounts of binary data.
When using Microsoft SQL Server, this data type is called image.
For more information, see BLOB (Binary Large OBject) for a short
definition, and Books Online for a complete reference.
The client has to obtain the data from the file in binary format
a byte
array
and call a procedure on the server with that array as a parameter.
The SQL Server procedures
In this presentation, I assume that I have a database Pictures on the
server with a table called Pictures. The structure of this table is as
follows:
Field NameField Type
kFileNameLong
PictureImage
FileNameVarchar(250)
I also have stored procedures for uploading, downloading, and retrieving
the list of uploaded files. These are shown below.
For uploading a file: UploadFile:
CREATE PROCEDURE [dbo].[UploadFile]
(
@Picture image,
@FileName varchar(250),
@kFileName bigint output
)
AS
insert into Pictures(Picture, FileName) values (@Picture,@FileName)
select @kFileName = SCOPE_IDENTITY()
GOFor downloading a file: DownloadFile:
CREATE PROCEDURE [dbo].[DownloadFile]
(
@kFileName bigint,
@FileName varchar(250) output
)
AS

select Picture, FileName


from Pictures
where kFileName=@kFileName
GOFor retrieving the list of uploaded files: getUploadedFiles:
CREATE PROCEDURE [dbo].[getUploadedFiles]AS
Select ltrim(str(kFileName)) + " - " + FileName as Name
from Pictures
GOThe C# Class - with comments
using System;
using System.IO;
using System.Data;
using System.Text;
using System.Data.SqlClient;
/*
* Autor: Ghiondea Alexandru
* Date: 08 october 2004
* Description: Implements methods for uploading and downloading files
* with MS SQL Server
* */
namespace PicturesInSQLServer
{
/// <SUMMARY>
/// This class manages uploads and downloads to and from an SQL Server
/// </SUMMARY>
public class TransferPictures
{
/// <SUMMARY>
/// Gets from the server a list of uploaded files into a dataSet
/// </SUMMARY>
/// <PARAM name="ds">The dataset</PARAM>
/// <PARAM name="table">The table in the dataset</PARAM>
public void GetUploadedFiles(ref DataSet ds, string table)
{
//
// The variables required for connecting to the server.
//
SqlConnection conn =null;
SqlCommand cmd = null;
SqlDataAdapter da = null;
// ---------------------------------------------try
{
//
// If the table already exists, cleares its content. Else adds a new table.
//
if (ds.Tables.Contains(table))
ds.Tables[table].Clear();
else
ds.Tables.Add(table);
// ---------------------------------------------//
// Creates a connection to the database and initilizes the command
//
conn = new SqlConnection(ConnectionString());
cmd = new SqlCommand("getUploadedFiles",conn);
cmd.CommandType = CommandType.StoredProcedure;
// ----------------------------------------------

//
// Initializes the DataAdapter used for retrieving the data
//
da = new SqlDataAdapter(cmd);
// ---------------------------------------------//
// Opens the connection and populates the dataset
//
conn.Open();
da.Fill(ds,table);
conn.Close();
// ---------------------------------------------}
catch(Exception e)
{
//
// If an error occurs, we assign null to the result
// and display the error to the user,
// with information about the StackTrace for debugging purposes.
//
Console.WriteLine(e.Message + " - " + e.StackTrace);
}
}
/// <SUMMARY>
/// Uploads a file to the database server.
/// </SUMMARY>
/// <PARAM name="fileName">The filename of the picture to be uploaded</PARAM>
/// <RETURNS>The id of the file on the server.</RETURNS>
public long UploadFile(string FileName)
{
if (!File.Exists(FileName))
{
return -1;
}
FileStream fs=null;
try
{
#region Reading file
fs = new FileStream(FileName,FileMode.Open);
//
// Finding out the size of the file to be uploaded
//
FileInfo fi = new FileInfo(FileName);
long temp = fi.Length;
int lung = Convert.ToInt32(temp);
// -----------------------------------------//
// Reading the content of the file into an array of bytes.
//
byte[] picture=new byte[lung];
fs.Read(picture,0,lung);
fs.Close();
// ------------------------------------------

#endregion
long result = uploadFileToDatabase(picture,fi.Name);
return result;
}
catch(Exception e)
{
Console.WriteLine(e.Message + " - " + e.StackTrace);
return -1;
}
}
/// <SUMMARY>
/// Wrapper for downloading a file from a database.
/// </SUMMARY>
/// <PARAM name="kFileName">The Unique ID of the file in database</PARAM>
/// <PARAM name="fileName">The file name as it was stored
///
in the database.</PARAM>
/// <RETURNS>The byte array required OR null if the ID is not found</RETURNS>
public byte[] DownloadFile(long kFileName, ref string fileName)
{
byte[] result = downloadFileFromDatabase(kFileName, ref fileName);
return result;
}
/// <SUMMARY>
/// Returns the connection string for connecting to the database
/// </SUMMARY>
/// <RETURNS>The Connection string.</RETURNS>
public static string ConnectionString()
{
//
// We consider that the database is situated
// on the same computer that runs the program.
// To connect to a remote server, replace 'Data Source'
// with the name of that server.
//
return "Connect Timeout=600;Integrated Security=SSPI;" +
"Persist Security Info=False;Initial Catalog=Pictures;" +
"Packet Size=4096;Data Source=" +
System.Environment.MachineName.Trim();
}
/// <SUMMARY>
/// Uploades a file to an SQL Server.
/// </SUMMARY>
/// <PARAM name="picture">A byte array that contains
///
the information to be uploaded.</PARAM>
/// <PARAM name="fileName">The file name asociated
///
with that byte array.</PARAM>
/// <RETURNS>The unique ID of the file on the server
///
OR -1 if an error occurs.</RETURNS>
private long uploadFileToDatabase(byte[] picture, string fileName)
{
//
// Defining the variables required for accesing the database server.
//
SqlConnection conn = null;
SqlCommand cmd =null;
SqlParameter kFileName =null;

SqlParameter FileName =null;


SqlParameter pic =null;
// By default, we assume we have an error. If we succed in uploading
// the file, we'll change this
// to the unique id of the file
long result=-1;
try
{
//
// Connecting to database.
//
conn = new SqlConnection(ConnectionString());
cmd = new SqlCommand("UploadFile",conn);
// We assume there is a stored procedure called UploadFile
cmd.CommandType = System.Data.CommandType.StoredProcedure;
// ---------------------------------------------//
// Initializing parameters and assigning
// the values to be sent to the server
//
kFileName = new SqlParameter("@kFileName",
System.Data.SqlDbType.BigInt,8);
kFileName.Direction = ParameterDirection.Output;
// This parameter does not have a size because
// we do not know what the size is going to be.
pic = new SqlParameter("@picture",SqlDbType.Image);
pic.Value = picture;
FileName = new SqlParameter("@FileName",SqlDbType.VarChar,250);
FileName.Value = fileName;
// ---------------------------------------------//
// Adding the parameters to the database.
// Remember that the order in which the parameters
// are added is VERY important!
//
cmd.Parameters.Add(pic);
cmd.Parameters.Add(FileName);
cmd.Parameters.Add(kFileName);
// ---------------------------------------------//
// Opening the connection and executing the command.
//
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
// ---------------------------------------------//
// The result is the unique identifier created on the database.
//
result = (long)kFileName.Value;
// ---------------------------------------------//

// Disposing of the objects so we don't occupy memory.


//
conn.Dispose();
cmd.Dispose();
// ---------------------------------------------}
catch(Exception e)
{
//
// If an error occurs, we report it to the user,
// with StackTrace for debugging purposes
//
Console.WriteLine(e.Message + " - " + e.StackTrace);
result = -1;
// ---------------------------------------------}
return result;
}
/// <SUMMARY>
/// Downloades a file from a database according
// to the unique id in that database.
/// </SUMMARY>
/// <PARAM name="kFile">The ID of the file in the database</PARAM>
/// <PARAM name="FileName">The filename of the file
///
as it was stored in the database.</PARAM>
/// <RETURNS>A byte array containing
///
the information required.</RETURNS>
private byte[] downloadFileFromDatabase(long kFile, ref string FileName)
{
SqlConnection conn =null;
SqlCommand cmd = null;
SqlParameter kFileName = null;
SqlParameter fileName = null;
SqlDataReader dr=null;
byte[] result=null;
try
{
//
// Connecting to database.
//
conn = new SqlConnection(ConnectionString());
cmd = new SqlCommand("DownloadFile",conn);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
// ---------------------------------------------//
// Initializing parameters and assigning the values to be sent to the server
//
kFileName= new SqlParameter("@kFileName",System.Data.SqlDbType.BigInt,8);
kFileName.Value = kFile;
fileName = new SqlParameter("@FileName",SqlDbType.VarChar,250);
fileName.Direction = ParameterDirection.Output;
// ---------------------------------------------//
// Adding the parameters to the database.

// Remember that the order in which the parameters


// are added is VERY important!
//
cmd.Parameters.Add(kFileName);
cmd.Parameters.Add(fileName);
// ---------------------------------------------//
// Opening the connection and executing the command.
// The idea behind using a dataReader is that,
// on the SQL Server, we cannot assign to a
// variable the value of an image field.
// So, we use a querry to select the record we want
// and we use a datareader to read that query.
// Because we are returnig information based
// on a primary key, we are always returning
// only one row of data.
//
conn.Open();
dr = cmd.ExecuteReader();
dr.Read();
//
// We are casting the value returned
// by the datareader to the byte[] data type.
//
result = (byte[])dr.GetValue(0);
//
// We are also returning the filename associated with the byte array.
//
FileName = (string)dr.GetValue(1);
//
// Closing the datareader and the connection
//
dr.Close();
conn.Close();
// -----------------------------------------//
// Disposing of the objects so we don't occupy memory.
//
conn.Dispose();
cmd.Dispose();
// -----------------------------------------}
catch(Exception e)
{
//
// If an error occurs, we assign null
// to the result and display the error to the user,
// with information about the StackTrace for debugging purposes.
//
Console.WriteLine(e.Message + " - " + e.StackTrace);
result = null;
}
return result;
}
}
}A sample application
I have also written a small application to demonstrate how to use these

methods. A screenshot of it is shown below:


The application uploads a file to the server and displays a list of files
on the server. When double-click-ing on the filename in the list, the file
is downloaded and displayed in the picture box.
Below are some snippets of relevant code:
private void UploadedFiles_DoubleClick(object sender, System.EventArgs e)
{
//
// Finds the unique id of the file.
//
DataRowView drv = (DataRowView) UploadedFiles.SelectedItem;
string selectedText = drv.Row["Name"].ToString();
long id=-1;
id = long.Parse(selectedText.Substring(0,selectedText.IndexOf(" - ",0)).Trim(
));
string filename=null;
TransferPictures up = new TransferPictures();
byte[] result = up.DownloadFile(id,ref filename);
up = null;
try
{
//
// We cannot assign a byte array directly to an image.
// We use MemoryStream, an object that creates a file in memory
// and than we pass this to create the image object.
//
MemoryStream ms= new MemoryStream(result,0,result.Length);
Image im = Image.FromStream(ms);
Picture.Image = im;
}
catch(Exception ee)
{
MessageBox.Show("An error has occured.\n" + ee.Message);
}
}
private void UploadFile_Click(object sender, System.EventArgs e)
{
//
// Gets the file to be uploaded
//
OpenFileDialog ofd = new OpenFileDialog();
ofd.ShowDialog();
if (ofd.FileName=="" || !File.Exists(ofd.FileName))
{
//
// If the requested file is not ok...
//
return;
}
TransferPictures up = new TransferPictures();
long id =up.UploadFile(ofd.FileName);
string msg=null;
if (id >0)
{
msg = "Upload succesful";
LoadInformationFromDataBase();

}
else
{
msg = "An error has occured";
}
MessageBox.Show(msg);
}
private void LoadInformationFromDataBase()
{
TransferPictures up = new TransferPictures();
up.GetUploadedFiles(ref ds,"Pictures");
UploadedFiles.DataSource = ds.Tables["Pictures"];
UploadedFiles.DisplayMember = "Name";
}
private void frmMain_Load(object sender, System.EventArgs e)
{
LoadInformationFromDataBase();
}Conclusion
Well, choosing which type of image
file
storage technique to use is up
to the person designing a specific application. I have tried here to show
you how you can store them in a database. Happy coding!
Bibliography
Books Online
MSDN
About Alexandru Ghiondea
Student at the Computer Science Faculty in Bucharest
Click here to view Alexandru Ghiondea's online profile.
Other popular articles:
QueryCommander SQL Editor
QueryCommander SQL editor with IntelliSense, wrapped in a Visual
Studio type of environment. QueryCommander supports: Microsoft SQL
Server 6.5-2005, MySQL 4.*-5.1, and Oracle 9i.
SQL Injection Attacks and Some Tips on How to Prevent Them
Discusses various aspects of SQL Injection attacks, what to look
for in your code, and how to secure it against SQL Injection
attacks.
SQL Server DO's and DONT's
SQL Server database best practices
Inserting relational data using DataSet and DataAdapter
This article describes the process of inserting data in a DataSet
and then submitting this changes to the database. It targets the
issue when having IDENTITY/AutoNumber columns in the database.
[Top]Sign in to vote for this article:

PoorExcellent

Premium Sponsor
FAQ Noise level Very High High Medium Low Very low Search
comments
View Normal (slow) Preview (slow) Message View Topic View

Thread View Expanded (Supporters only) Per page 10 25 50


(must logon)
New threadMsgs 1 to 12 of 12 (Total: 12) (Refresh)First Prev
Next
Subject Author Date
a problem with the code Shanyok 8:59 5 Mar '05
Hi Alex
Good example!!
I got exception at this line - "id =
long.Parse(selectedText.Substring(0,selectedText
.IndexOf("
- ",0)).Trim());"
An unhandled exception of type
'System.ArgumentOutOfRangeException' occurred in
mscorlib.dll Additional information: Length
cannot be less than zero.
I didn't change the code..this is what so weird
here....
do u have any idea what is the problem might be
?

[Reply][Email][View Thread][Get
Link][Modify|Delete]

Re: a problem with the code Alexandru Ghiondea 14:30 5


Mar '05
Hello and Thank you for your appreciation.
First of all I would like to ask you a few
questions about how did that error occured. I
mean what did you do to get that error.
Secondly, the line of code does a simple thing.
It separates the id of the file in the database
from the filename used to upload it.
So, if you have an entry like 1 somePicture.bmp the code will extract the
portion from the beginning of the string to the
- character (i.e. 1), and it will try to convert
that string to a long in order to request the

file with that id from the server.


Anyway, please provide some extra information
about what do you do to get that error and I
will try to answer it.
[Reply][Email][View Thread][Get
Link][Modify|Delete]
Score: 2.0 (1 vote).

Re: a problem with the code Shanyok 15:21 5 Mar '05


Hi Alex
Thank you for your response
ok...I found the problem... the id-file_name
were shown in the listview in different order.
"1 -somePicture.bmp" instead of "1 somePicture.bmp" . there wasn't white space
between "-" and the "file_name". so after I
changed the code to :
id =
long.Parse(selectedText.Substring(0,selectedText
.IndexOf("
-",0)).Trim());
it started working perfectly.
I looked at the SP but it looks fine
CREATE PROCEDURE [dbo].[getUploadedFiles]
AS select ltrim(str(kFileName)) + " - " +
FileName as Name from Pictures GO
so I don't know yet why all the items in the
Uploadedfiles listview are presented without the
white space between "-" and "filename"
[Reply][Email][View Thread][Get
Link][Modify|Delete]

Re: a problem with the code Alexandru Ghiondea 15:46 5


Mar '05
I'm glad you got it to work.
I can't imagine why it wouldn't work. I will
think about that an if I find an answer, I'll
let you know.
Try to download it again from the site. See if
it works. But, since you got it to work, I don't
see the point.

Happy coding!
[Reply][Email][View Thread][Get
Link][Modify|Delete]

To save all types of file in Sql Server alijhon 9:22 4


Feb '05
hi!,
Very Good article,
My requirment is to upload all types of files to
a Microsoft Sql Server 2000 and download them to
modify through an ASP.net. do i have to use
image data type for saving all types of
documents.
pls provide some help,
thank you,
~ALI~
[Reply][Email][View Thread][Get
Link][Modify|Delete]

Re: To save all types of file in Sql Server Alexandru


Ghiondea 3:24 7 Feb '05
Hello.
Thank you for your apreciation.
The answer to your question is YES. For any type
of files, you have to use the Image datatype.
The reason for doing that is that, in SQL
Server, the Image datatype is used as a BLOB
field. So, you can upload any stream of bytes
into an Image field.
Hope this helps and, for other questions, don't
hesitate.
Alex.
[Reply][Email][View Thread][Get
Link][Modify|Delete]

To upload all file types through ASP.net manoyaka 3:58


30 Dec '04
hi!,
thanks for your article,
My requirment is to upload all types of files to
a database and download them to modify through
an ASP.net.
pls provide some help,
thank you,
mano
[Reply][Email][View Thread][Get
Link][Modify|Delete]

Re: To upload all file types through ASP.net Alexandru


Ghiondea 7:04 8 Jan '05
Hello and thank you for your message.
If I understand correctly you want to store any
type of file in your SQL Server.
Well, as I wrote in the article, you can do that
just fine using the code I presented. I chose to
focus the application on images because I needed
pictures in an application I wrote.
So, you can use this program for any type of
files!!!
About processing them with ASP.NET, can you be
more clear about what you want to do?
Best Regards,
Alexandru Ghiondea
[Reply][Email][View Thread][Get
Link][Modify|Delete]

is it recomended? Jordi Corominas 6:14 25 Nov '04

Hi!
I'm interested in storinc pictures or word
documents for an application i'm developping but
i'm not sure if this is the best way to do it. I
have been trying to store the pictures to the
server (in a folder) and store at the DB the
path of the picture.
What do you think is better to store the entire
pic to the DB or my way of storing only the
path?
Thanks!
Jordi
"Catalonia is not Spain"
[Reply][Email][View Thread][Get
Link][Modify|Delete]

Re: is it recomended? Alexandru Ghiondea 9:49 25 Nov


'04
Hi.
In the application I used pictures, but the code
I presented allows you to upload any type of
file.
Anyway. To answer your question like my teachers
did: It all depends .
I can give you some ideas to think about:
1. If you store the pictures in the database,
without your application it can be rather
difficult to acces it. If you store it in a
file, you don't have this problem.
2. It depends on the size of the pictures. If
you store them in a database, you will have to
download them before doing anything, and this
may cause slow response in your application.
3. If you have a lot of small files, it will be
difficult for you to acces the required one
manually, especially when the file names are
filenamexxx.
4. If security is an issue, you might consider
the database because, with a database you have
the database system as another security
mechanism.

I hope that what I said will help you decide. If


you need further help, don't hesitate to email
me.
Sincerely,
Alexandru Ghiondea
[Reply][Email][View Thread][Get
Link][Modify|Delete]

@@IDENTITY bug jlb 14:15 2 Nov '04


I noticed you were using @@IDENTITY to retrieve
the identity of the row in the picture column.
This really should be a call to SCOPE_IDENTITY()
instead just in case some future trigger on this
table (for auditing perhaps) inserts its own
row. HTH.
Regards, John B.
[Reply][Email][View Thread][Get
Link][Modify|Delete]
Score: 5.0 (1 vote).

Re: @@IDENTITY bug Alexandru Ghiondea 3:46 3 Nov '04


You are correct, and I changed my code to
obtain the @@IDENTITY usint Scope_Identity. I
didn't think about this type of problem when I
originally wrote the article.
Thank you for interest and observation, Alex G.
[Reply][Email][View Thread][Get
Link][Modify|Delete]

Last Visit: 11:53 Wednesday 13th April, 2005First Prev Next

ASP.NET, All Topics, C#, .NET >> C# Database >> General

Updated: 29 Oct 2004 4:49 Article content copyright Alexandru Ghiondea,


2004
everything else Copyright CodeProject, 1999-2005.
Advertise on The Code Project | Privacy

MSDN Communities | ASP Alliance


Developer Fusion
DevGuru
Programmers Heaven Planet Source Code

Developersdex
Tek-Tips Forums

Help!ArticlesMessage BoardsStoreFrontLoungeWhat is 'The Code Project'?General


FAQPost a QuestionSite DirectoryAbout UsLatestMost PopularSearchSite
DirectorySubmit an ArticleUpdate an ArticleArticle CompetitionVisual C++ATL /
WTL / STLCOMManaged C++C#ASP.NETVB.NETWeb Development.NET FrameworkSQL / ADO /
ADO.NETXML / XSLOS / SysAdminWork IssuesArticle RequestsCollaborationGeneral
DiscussionsSuggestionsThe Soapbox

You might also like