Несмотря на довольно спорные преимущества использование 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-полей в большинстве стандартных ситуаций вряд ли можно назвать оправданным шагом.
Кристофер
Комментарии
В BLOB маловато места - всего 64 килобайта. Лучше брать MEDIUMBLOB, если, конечно, картинка - не смайлик.
«640 килобайт должно хватить всем» :) А один сегмент в те времена был как раз 64 КБ.