6

MySQL データベースから 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 のタイプを選択できるようになりました。物事は最終的に意図したとおりに機能しています:)

4

1 に答える 1

3

最初に単純化してみましたか?一度に100バイトずつBLOBを読み取る代わりに、コードを単純化して、ファイルのすべてのバイトを読み取るようにしてください。このようにして、データレイヤーの問題を簡単に除外できます。

次のドキュメントでは、ファイルサイズを別の列として保存することも提案しています。Connector/NETを使用したBLOBデータの処理

于 2012-07-25T09:26:56.410 に答える