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 Name |
Field Type |
kFileName
|
Long
|
Picture
|
Image
|
FileName
|
Varchar(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()
GO
For downloading a file: DownloadFile
:
CREATE PROCEDURE [dbo].[DownloadFile]
(
@kFileName bigint,
@FileName varchar(250) output
)
AS
select Picture, FileName
from Pictures
where kFileName=@kFileName
GO
For retrieving the list of uploaded files: getUploadedFiles
:
CREATE PROCEDURE [dbo].[getUploadedFiles]AS
Select ltrim(str(kFileName)) + " - " + FileName as Name
from Pictures
GO
The C# Class - with comments
using System;
using System.IO;
using System.Data;
using System.Text;
using System.Data.SqlClient;
namespace PicturesInSQLServer
{
public class TransferPictures
{
public void GetUploadedFiles(ref DataSet ds, string table)
{
SqlConnection conn =null;
SqlCommand cmd = null;
SqlDataAdapter da = null;
try
{
if (ds.Tables.Contains(table))
ds.Tables[table].Clear();
else
ds.Tables.Add(table);
conn = new SqlConnection(ConnectionString());
cmd = new SqlCommand("getUploadedFiles",conn);
cmd.CommandType = CommandType.StoredProcedure;
da = new SqlDataAdapter(cmd);
conn.Open();
da.Fill(ds,table);
conn.Close();
}
catch(Exception e)
{
Console.WriteLine(e.Message + " - " + e.StackTrace);
}
}
public long UploadFile(string FileName)
{
if (!File.Exists(FileName))
{
return -1;
}
FileStream fs=null;
try
{
#region Reading file
fs = new FileStream(FileName,FileMode.Open);
FileInfo fi = new FileInfo(FileName);
long temp = fi.Length;
int lung = Convert.ToInt32(temp);
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;
}
}
public byte[] DownloadFile(long kFileName, ref string fileName)
{
byte[] result = downloadFileFromDatabase(kFileName, ref fileName);
return result;
}
public static string ConnectionString()
{
return "Connect Timeout=600;Integrated Security=SSPI;" +
"Persist Security Info=False;Initial Catalog=Pictures;" +
"Packet Size=4096;Data Source=" +
System.Environment.MachineName.Trim();
}
private long uploadFileToDatabase(byte[] picture, string fileName)
{
SqlConnection conn = null;
SqlCommand cmd =null;
SqlParameter kFileName =null;
SqlParameter FileName =null;
SqlParameter pic =null;
long result=-1;
try
{
conn = new SqlConnection(ConnectionString());
cmd = new SqlCommand("UploadFile",conn);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
kFileName = new SqlParameter("@kFileName",
System.Data.SqlDbType.BigInt,8);
kFileName.Direction = ParameterDirection.Output;
pic = new SqlParameter("@picture",SqlDbType.Image);
pic.Value = picture;
FileName = new SqlParameter("@FileName",SqlDbType.VarChar,250);
FileName.Value = fileName;
cmd.Parameters.Add(pic);
cmd.Parameters.Add(FileName);
cmd.Parameters.Add(kFileName);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
result = (long)kFileName.Value;
conn.Dispose();
cmd.Dispose();
}
catch(Exception e)
{
Console.WriteLine(e.Message + " - " + e.StackTrace);
result = -1;
}
return result;
}
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
{
conn = new SqlConnection(ConnectionString());
cmd = new SqlCommand("DownloadFile",conn);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
kFileName= new SqlParameter("@kFileName",System.Data.SqlDbType.BigInt,8);
kFileName.Value = kFile;
fileName = new SqlParameter("@FileName",SqlDbType.VarChar,250);
fileName.Direction = ParameterDirection.Output;
cmd.Parameters.Add(kFileName);
cmd.Parameters.Add(fileName);
conn.Open();
dr = cmd.ExecuteReader();
dr.Read();
result = (byte[])dr.GetValue(0);
FileName = (string)dr.GetValue(1);
dr.Close();
conn.Close();
conn.Dispose();
cmd.Dispose();
}
catch(Exception e)
{
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)
{
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
{
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)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.ShowDialog();
if (ofd.FileName=="" || !File.Exists(ofd.FileName))
{
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