|
26.2.4.5. Handling BLOB Data With Connector/NET
One common use for MySQL is the storage of binary data in
BLOB columns. MySQL supports four different
BLOB datatypes: TINYBLOB ,
BLOB , MEDIUMBLOB , and
LONGBLOB .
Data stored in a BLOB column can be accessed using
Connector/NET and manipulated using client-side code. There
are no special requirements for using Connector/NET with BLOB
data.
Simple code examples will be presented within this section,
and a full sample application can be found in the
Samples directory of the MySQL Connector/NET
installation.
26.2.4.5.2. Preparing the MySQL Server
The first step is using MySQL with BLOB data is to configure
the server. Let's start by creating a table to be accessed. In
my file tables, I usually have four columns: an AUTO_INCREMENT
column of appropriate size (UNSIGNED SMALLINT) to serve as a
primary key to identify the file, a VARCHAR column that stores
the filename, an UNSIGNED MEDIUMINT column that stores the
size of the file, and a MEDIUMBLOB column that stores the file
itself. For this example, I will use the following table
definition:
CREATE TABLE file(
file_id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
file_name VARCHAR(64) NOT NULL,
file_size MEDIUMINT UNSIGNED NOT NULL,
file MEDIUMBLOB NOT NULL);
After creating a table, you may need to modify the
max_allowed_packet system variable. This variable determines
how large of a packet (i.e. a single row) can be sent to the
MySQL server. By default, the server will only accept a
maximum size of 1 meg from our client application. If you do
not intend to exceed 1 meg, this should be fine. If you do
intend to exceed 1 meg in your file transfers, this number has
to be increased.
The max_allowed_packet option can be modified using MySQL
Administrator's Startup Variables screen. Adjust the Maximum
allowed option in the Memory section of the Networking tab to
an appropriate setting. After adjusting the value, click the
Apply Changes button and restart the
server using the Service Control screen of
MySQL Administrator. You can also adjust this value directly
in the my.cnf file (add a line that reads
max_allowed_packet=xxM), or use the SET
max_allowed_packet=xxM; syntax from within MySQL.
Try to be conservative when setting max_allowed_packet, as
transfers of BLOB data can take some time to complete. Try to
set a value that will be adequate for your intended use and
increase the value if necessary.
26.2.4.5.3. Writing a File to the Database
To write a file to a database we need to convert the file to a
byte array, then use the byte array as a parameter to an
INSERT query.
The following code opens a file using a FileStream object,
reads it into a byte array, and inserts it into the
file table:
[VB]
Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand
Dim SQL As String
Dim FileSize As UInt32
Dim rawData() As Byte
Dim fs As FileStream
conn.ConnectionString = "server=127.0.0.1;" _
& "uid=root;" _
& "pwd=12345;" _
& "database=test"
Try
fs = New FileStream("c:\image.png", FileMode.Open, FileAccess.Read)
FileSize = fs.Length
rawData = New Byte(FileSize) {}
fs.Read(rawData, 0, FileSize)
fs.Close()
conn.Open()
SQL = "INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)"
cmd.Connection = conn
cmd.CommandText = SQL
cmd.Parameters.Add("?FileName", strFileName)
cmd.Parameters.Add("?FileSize", FileSize)
cmd.Parameters.Add("?File", rawData)
cmd.ExecuteNonQuery()
MessageBox.Show("File Inserted into database successfully!", _
"Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
conn.Close()
Catch ex As Exception
MessageBox.Show("There was an error: " & ex.Message, "Error", _
MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
string SQL;
UInt32 FileSize;
byte[] rawData;
FileStream fs;
conn.ConnectionString = "server=127.0.0.1;uid=root;" +
"pwd=12345;database=test;";
try
{
fs = new FileStream(@"c:\image.png", FileMode.Open, FileAccess.Read);
FileSize = fs.Length;
rawData = new byte[FileSize];
fs.Read(rawData, 0, FileSize);
fs.Close();
conn.Open();
SQL = "INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)";
cmd.Connection = conn;
cmd.CommandText = SQL;
cmd.Parameters.Add("?FileName", strFileName);
cmd.Parameters.Add("?FileSize", FileSize);
cmd.Parameters.Add("?File", rawData);
cmd.ExecuteNonQuery();
MessageBox.Show("File Inserted into database successfully!",
"Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
conn.Close();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
The Read method of the
FileStream object is used to load the file
into a byte array which is sized according to the
Length property of the FileStream object.
After assigning the byte array as a parameter of the
MySqlCommand object, the
ExecuteNonQuery method is called and the
BLOB is inserted into the file table.
26.2.4.5.4. Reading a BLOB from the Database to a File on Disk
Once a file is loaded into the file table,
we can use the MySqlDataReader class to
retrieve it.
The following code retrieves a row from the
file table, then loads the data into a
FileStream object to be written to disk:
[VB]
Dim conn As New MySqlConnection
Dim cmd As New MySqlCommand
Dim myData As MySqlDataReader
Dim SQL As String
Dim rawData() As Byte
Dim FileSize As UInt32
Dim fs As FileStream
conn.ConnectionString = "server=127.0.0.1;" _
& "uid=root;" _
& "pwd=12345;" _
& "database=test"
SQL = "SELECT file_name, file_size, file FROM file"
Try
conn.Open()
cmd.Connection = conn
cmd.CommandText = SQL
myData = cmd.ExecuteReader
If Not myData.HasRows Then Throw New Exception("There are no BLOBs to save")
myData.Read()
FileSize = myData.GetUInt32(myData.GetOrdinal("file_size"))
rawData = New Byte(FileSize) {}
myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, FileSize)
fs = New FileStream("C:\newfile.png", FileMode.OpenOrCreate, FileAccess.Write)
fs.Write(rawData, 0, FileSize)
fs.Close()
MessageBox.Show("File successfully written to disk!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
myData.Close()
conn.Close()
Catch ex As Exception
MessageBox.Show("There was an error: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataReader myData;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
string SQL;
UInt32 FileSize;
byte[] rawData;
FileStream fs;
conn.ConnectionString = "server=127.0.0.1;uid=root;" +
"pwd=12345;database=test;";
SQL = "SELECT file_name, file_size, file FROM file";
try
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = SQL;
myData = cmd.ExecuteReader();
if (! myData.HasRows)
throw new Exception("There are no BLOBs to save");
myData.Read();
FileSize = myData.GetUInt32(myData.GetOrdinal("file_size"));
rawData = new byte[FileSize];
myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, FileSize);
fs = new FileStream(@"C:\newfile.png", FileMode.OpenOrCreate, FileAccess.Write);
fs.Write(rawData, 0, FileSize);
fs.Close();
MessageBox.Show("File successfully written to disk!",
"Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
myData.Close();
conn.Close();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
After connecting, the contents of the file
table are loaded into a MySqlDataReader
object. The GetBytes method of the
MySqlDataReader is used to load the BLOB into a byte array,
which is then written to disk using a FileStream object.
The GetOrdinal method of the
MySqlDataReader can be used to determine the integer index of
a named column. Use of the GetOrdinal method prevents errors
if the column order of the SELECT query is changed.
|
|