【问题标题】:reading BLOB image from MySQL database从 MySQL 数据库中读取 BLOB 图像
【发布时间】:2012-07-16 14:14:34
【问题描述】:

我在从 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);出现错误“GetBytes 只能在二进制或 guid 列上调用”。我假设这与我的数据库中的字段类型有关,但是将列更改为二进制类型意味着我必须将其存储为 blob 类型,但我想将文件名保留为常规字符串。有什么我想念的吗?还是其他方式?

edit1 :我认为 bytesreturned 的第一个参数与读取器中的列有关,将其设置为 0 会给出错误“使用 SequentialAccess 读取先前列的尝试无效”,请对此进行调查。

edit2:删除顺序访问给我一个大小为 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”(derp)类型,它允许我选择 blob 类型。事情终于按预期工作了:)

【问题讨论】:

  • 我不是 C# 专家,但您选择了 2 列 - siteMapPicture siteBlobFilename - 都是 blob 还是一个 varchar/char/text?
  • siteMapPicture 是 BLOB,siteBlobFilename 是 varchar
  • 不是 c# 开发人员,但您的 blob 字段不会是第 0 列,而您正在尝试获取第 1 列上的字节,这将是路径字段?
  • 我刚刚在大约 30 分钟前在测试时移动了这个,它不再出错了,虽然它只给出了一个大小为 13 的文件...我可能会检查我存储的 blob绝对完好无损。

标签: c# .net mysql blob


【解决方案1】:

您是否尝试过先简化?与其一次读取 100 个字节的 BLOB,不如尝试简化代码以将所有字节读取到文件中。这样您就可以轻松排除数据层问题。

以下文档还建议您将文件大小存储为另一列:Handling BLOB Data With Connector/NET

【讨论】:

    猜你喜欢
    • 2015-01-23
    • 1970-01-01
    • 2014-08-20
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    • 2014-02-19
    • 2010-10-23
    • 2012-03-27
    相关资源
    最近更新 更多