Tôi đang gặp sự cố khi đọc lại blob từ cơ sở dữ liệu MySQL. Tôi đã nhận được nó để chèn thành công vào cơ sở dữ liệu, nhưng dường như không thể làm cho nó đọc lại. Tôi biết một số bạn có thể nghĩ "tại sao anh ấy sử dụng cơ sở dữ liệu để lưu trữ các đốm màu cho hình ảnh chứ không chỉ tên đường dẫn/tên tệp", nhưng tôi muốn có tính linh hoạt và nhiều ảnh này sẽ được lưu trữ trên máy chủ và không cục bộ, điều này tối ưu hóa hiệu quả, cũng như cho phép tôi di chuyển hình ảnh đến địa phương nếu cần. Tôi đã làm theo một hướng dẫn (ngắn) và đã viết phương pháp sau đây để nhận một đốm màu;đọc hình ảnh BLOB từ cơ sở dữ liệu MySQL
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();
}
}
và tôi gọi nó như vậy ..
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);
Tuy nhiên nó erroring trên BytesReturned = reader.GetBytes (1, CurrentIndex, Blob, 0, BUFFERSIZE); với lỗi "GetBytes chỉ có thể được gọi trên cột nhị phân hoặc guid". Tôi giả sử điều này là để làm với loại trường của tôi trong cơ sở dữ liệu của tôi, nhưng thay đổi cột để loại nhị phân có nghĩa là tôi phải lưu trữ nó như là một loại blob, nhưng tôi muốn để lại tên tập tin giống như một chuỗi thông thường. Có cái gì tôi đang thiếu? hoặc một cách khác để làm điều này?
edit1: tôi nghĩ tham số đầu tiên cho bytesreturned là làm với cột trong trình đọc, đặt giá trị này thành 0 cho lỗi "Cố gắng không hợp lệ để đọc cột trước bằng cách sử dụng SequentialAccess", bị xem xét điều này.
edit2: Xóa quyền truy cập tuần tự cho tôi tệp có kích thước 13 byte, (có thể chỉ là hàng đầu tiên, đó là lý do tại sao truy cập tuần tự đọc tất cả các hàng?) Vì vậy có thể tôi đang đọc các cột theo thứ tự sai.
chỉnh sửa 3: tôi tin rằng lý do của lỗi này là do cách tôi nhập vào cơ sở dữ liệu. đã thay đổi phương pháp này, saveBlob của tôi bây giờ trông giống như vậy:
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();
}
}
tôi đã chạy qua debugger, và cả hai blobvalue và blobfileparam (@blobfile) có kích thước đầy đủ (khoảng 150k), nhưng nó erroring khi thực hiện truy vấn, đưa ra lỗi sau;
"unable to cast object of type 'system.byte[]' to type 'system.iconvertible"
Tôi đã xem xét mã và cố gắng thay đổi loại nhị phân thành hình ảnh, để cho phép các tệp lớn hơn, nhưng cũng cho cùng một lỗi. Có ai biết gì về thông tin mới này không?
chỉnh sửa 4: cố định mọi thứ. nhận thấy rằng trong mã của tôi, tôi đã được sử dụng:
("@BlobFile", SqlDbType.Binary);
Thay đổi này để loại "MySqlDbType" (derp) và nó cho phép tôi để lựa chọn loại blob. Mọi thứ cuối cùng cũng hoạt động như dự định:)
Tôi không phải C# chuyên gia, nhưng bạn đang chọn 2 cột - 'siteMapPicture' và 'siteBlobFilename' - đều blobs hoặc là một varchar/char/text? –
siteMapPicture là một BLOB, siteBlobFilename là một varchar –
Không phải là một nhà phát triển C#, nhưng sẽ không blob lĩnh vực của bạn được cột # 0, trong khi bạn đang cố gắng để getbytes trên cột # 1, đó sẽ là trường đường dẫn? –