我在读取MySQL数据库中的blob时遇到了一些问题。我已经成功地将它插入到数据库中,但似乎无法读回。我知道有些人可能会想“为什么他要使用数据库来存储图像的blob,而不是文件路径/文件名”,但我希望具备灵活性,因为很多这些图像将被存储在服务器上而不是本地,这可以优化效率,并允许我在需要时将图像移动到本地。我按照(简短的)教程编写了以下方法来接收blob:
public void getBlob(string query, string fileOut)
{
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, mConnection);
//the index number to write bytes to
long CurrentIndex = 0;
//the number of bytes to store in the array
int BufferSize = 100;
//The Number of bytes returned from GetBytes() method
long BytesReturned;
//A byte array to hold the buffer
byte[] Blob = new byte[BufferSize];
//We set the CommandBehavior to SequentialAccess
//so we can use the SqlDataReader.GerBytes() method.
MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
while (reader.Read())
{
FileStream fs = new FileStream(DeviceManager.picPath + "\\" + reader["siteBlobFileName"].ToString(), FileMode.OpenOrCreate, FileAccess.Write);
BinaryWriter writer = new BinaryWriter(fs);
CurrentIndex = 0;
BytesReturned = reader.GetBytes(1, CurrentIndex, Blob, 0,BufferSize);
while (BytesReturned == BufferSize)
{
writer.Write(Blob);
writer.Flush();
CurrentIndex += BufferSize;
BytesReturned = reader.GetBytes(1, CurrentIndex, Blob, 0, BufferSize);
}
writer.Write(Blob, 0, (int)BytesReturned);
writer.Flush();
writer.Close();
fs.Close();
}
reader.Close();
this.CloseConnection();
}
}
我正在这样调用它。
mDBConnector.getBlob("SELECT siteMapPicture, siteBlobFilename FROM sites WHERE siteID = '" + DeviceManager.lastSite + "'", DeviceManager.picPath + "mappicsite" + DeviceManager.lastSite);
PBSite.BackgroundImage = Image.FromFile(DeviceManager.picPath + "mappicsite" + DeviceManager.lastSite);
然而,当BytesReturned = reader.GetBytes(1, CurrentIndex, Blob, 0,BufferSize)时出错,并显示"只能在二进制或GUID列上调用GetBytes"。我猜这与我的数据库字段类型有关,但将列更改为二进制类型意味着我必须将其存储为一种blob类型,但我想将文件名保留为常规字符串。我是否遗漏了什么?或者还有其他方法可以实现这一点?
编辑1:我认为bytesreturned的第一个参数与reader中的列有关。将其设置为0会出现错误"尝试使用SequentialAccess读取先前的列无效",我将进一步研究。
编辑2:移除sequential access后,我得到了大小为13字节的文件(这可能是第一行),所以我可能正在错误地读取列的顺序...
编辑3:我认为产生此错误的原因是我的输入方式不正确。更改了此方法后,我的saveBlob现在如下所示:
public void saveBlob(string filePath, string fileName, string siteID)
{
if (this.OpenConnection() == true)
{
//A stream of bytes that represnts the binary file
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
//The reader reads the binary data from the file stream
BinaryReader reader = new BinaryReader(fs);
//Bytes from the binary reader stored in BlobValue array
byte[] BlobValue = reader.ReadBytes((int)fs.Length);
fs.Close();
reader.Close();
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = mConnection;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO x (y, z) VALUES (@BlobFile, @BlobFileName)";
MySqlParameter BlobFileNameParam = new MySqlParameter("@BlobFileName", SqlDbType.NChar);
MySqlParameter BlobFileParam = new MySqlParameter("@BlobFile", SqlDbType.Binary);
cmd.Parameters.Add(BlobFileNameParam);
cmd.Parameters.Add(BlobFileParam);
BlobFileNameParam.Value = fileName;
BlobFileParam.Value = BlobValue;
cmd.ExecuteNonQuery();
this.CloseConnection();
}
}
我已经通过调试器运行了程序,blobvalue和blobfileparam(@blobfile)的大小都是完整的(约150k),但在执行查询时出现错误,显示以下错误信息:
"unable to cast object of type 'system.byte[]' to type 'system.iconvertible"
我已经查看了代码,并尝试将类型从二进制更改为图像以允许更大的文件,但出现相同的错误。有人知道这个新信息的详情吗?
编辑4:一切都已经修复。我注意到在我的代码中使用了:
("@BlobFile", SqlDbType.Binary);
将这些类型更改为"MySqlDbType"(笨蛋),这样就可以选择Blob类型了。现在事情终于按预期工作了 :)
siteMapPicture
和siteBlobFilename
- 它们都是 BLOB 还是其中一个是 varchar/char/text? - N.B.