Работа с BLOB-полями (MySQL, C#)

Несмотря на довольно спорные преимущества использование BLOB-полей в базах данных MySQL, их можно встретить довольно часто. BLOB (Binary Large Object) — это специальный тип данных, который может хранить в себе различную информацию (изображения, видео, текст, программы, архивы) в двоичном представлении. Наиболее часто в вебе он используется для хранения картинок внутри таблиц БД, но и не только, например, вы можете сохранять в нем целые страницы и т.п.

В принципе, в стандартных ситуациях хранение картинок внутри таблиц в BLOB-полях ведет больше к раздутию объема этих самых таблиц. Если говорить о хранении текста в BLOB, тут тоже преимущество спорное, поскольку нужно будет специальным образом настраивать поиск по сайту.

С точки зрения PHP в Интернете есть множество информации по работе с BLOB, извлечения/загрузки картинок и тому подобного. Поэтому данный аспект мы затрагивать не будем.

Чуть хуже обстоят дела с информацией по работе с BLOB-полями на C#, хотя на самом деле ничего особенно сложного в этом нет, нужно только осуществить грамотное преобразование двоичных данных в нужное представление и обратно (если мы говорим о тексте).

Например, я считывал BLOB-поля с текстом и отображал в таблице с названием DataGridViewString по колонкам, используя следующую конструкцию (мне нужно было видеть текст и вносить в него изменения, это реальная ситуация, задачей было прописать alt для картинок в базе с 5000 товаров):

private DataTable data_bin;

private MySqlDataAdapter da;

private MySqlCommandBuilder cb;

//делаем коннект к БД

data_bin = new DataTable();

da = new MySqlDataAdapter(

       "SELECT * FROM `myDataBase`.`products`", conn);

cb = new MySqlCommandBuilder(da);

da.Fill(data_bin);

DataColumn column0 = data_bin.Columns.Add("name(string)", typeof(string));

foreach (DataRow rows in data_bin.Rows)

{

rows[column0] = Encoding.UTF8.GetString((byte[])rows["name"]);

}

DataColumn column1 = data_bin.Columns.Add("picture(string)", typeof(string));

foreach (DataRow rows in data_bin.Rows)

{

rows[column1] = Encoding.UTF8.GetString((byte[])rows["description"]);

}

data_bin.Columns.Remove("name");

data_bin.Columns.Remove("description");

DataGridViewString.DataSource = data_bin;

Принцип действия этого кода довольно прост, то есть в таблицу с бинарными данными добавляются новые колонки, в которые записывается уже преобразованные в текст, а бинарные удаляются.

Запись же в BLOB-поля производится по одному из способов, которые описаны в предыдущем ответе с одной лишь разницей, что вы должны помещать бинарные данные. Обратное преобразование, думаю вопросов не вызовет, это описано в любом справочнике:

byte[] name1 = Encoding.UTF8.GetBytes(dataGridViewString.Rows[i].Cells[1].Value.ToString().Trim());  

Если говорить об импорте/экспорте изображений из/в BLOB, то для первого случая (импорта) мы немного преобразуем предыдущий код, а именно, возьмем из таблицы БД поля с названием артикулов, считаем изображения в буфер, создадим стрим, и сохраним наши картинки в файлы с расширением jpg:

data_bin = new DataTable();

da = new MySqlDataAdapter(

       "SELECT `name`,`picture` FROM `myDataBase`.`products`", conn);

cb = new MySqlCommandBuilder(da);

da.Fill(data_bin);

foreach (DataRow rows in data_bin.Rows)

{

string str = "C:\\"+Encoding.UTF8.GetString((byte[])rows["name"])+".jpg";

byte[] Img = (byte[])rows["picture"];

FileStream fs = new FileStream(str, FileMode.CreateNew, FileAccess.Write);

fs.Write(Img, 0, Img.Length);

fs.Flush();

fs.Close();

}

В этом коде представлен самый простой случай, и по умолчанию подразумевается, что все файлы изображений являются Jpeg. В более сложных ситуациях необходимо использовать библиотеку Image.Drawing для преобразования бинарных данных в изображения. И этот вариант окажется лучшим, поскольку там имеется метод Save с принудительной конвертацией под заданный формат, например, для нашего случая:

Image image1 = new Bitmap(new MemoryStream((byte[])rows["picture"]);

image1.Save(str, System.Drawing.Imaging.ImageFormat.Jpeg);

На самом деле, вариантов может быть довольно много, поэтому экспериментируйте. Суть понятна — читаем данные в буфер byte[], создаем стрим (например, MemoryStream), пишем данные из буфера в стрим, затем перегоняем данные в нужный класс для работы с изображениями, производим конвертацию в нужный формат и сохраняем.

Что касается чтения файлов и преобразования их в бинарный вид, то тут обратное движение. В данном случае я покажу довольно стандартную функцию.

byte[] ReadImageToBytes(string sPath)

{

 byte[] data = null;

 //FileInfo для получения размера файла

 FileInfo fInfo = new FileInfo(sPath);

 long numBytes = fInfo.Length;

 //Открываем поток FileStream для чтения файла

 FileStream fStream = new FileStream(sPath, FileMode.Open, FileAccess.Read);

 //Используем BinaryReader и читаем данные в буфер byte[]

 BinaryReader br = new BinaryReader(fStream);

 data = br.ReadBytes((int)numBytes);

 return data;

}

А в общем и целом, использование BLOB-полей в большинстве стандартных ситуаций вряд ли можно назвать оправданным шагом.

Кристофер

christopher@tut.by

http://itcs.3dn.ru

Версия для печатиВерсия для печати

Рубрики: 

  • 1
  • 2
  • 3
  • 4
  • 5
Всего голосов: 0
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя Petro42

В BLOB маловато места - всего 64 килобайта. Лучше брать MEDIUMBLOB, если, конечно, картинка - не смайлик. 

«640 килобайт должно хватить всем» :) А один сегмент в те времена был как раз 64 КБ.