Рассмотрим, как мы можем сохранять файлы, в частности, файлы изображений в базу данных. Для этого вначале определим новую базу данных и в ней новую таблицу Files с четырьмя столбцами:
_id - первичный ключ и идентификатор, имеет тип INTEGER)
FileName будет хранить имя файла и имеет тип TEXT
Title будет хранить заголовок файла и также имеет тип TEXT
ImageData будет содержать бинарные данные файла и имеет тип BLOB
Для создания базы данных и таблицы для хранения файлов определим следующую программу:
using System; using Microsoft.Data.Sqlite; namespace HelloApp { class Program { static void Main(string[] args) { // выражение SQL для добавления данных string sqlExpression = @"CREATE TABLE Files (_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, Title TEXT NOT NULL, FileName TEXT NOT NULL, ImageData BLOB)"; using (var connection = new SqliteConnection("Data Source=filesdata.db")) { connection.Open(); SqliteCommand command = new SqliteCommand(sqlExpression, connection); command.ExecuteNonQuery(); Console.WriteLine("Таблица Files создана"); } Console.Read(); } } }
Определим код, в котором будут загружаться данные в таблицу:
using System; using System.Collections.Generic; using System.IO; using Microsoft.Data.Sqlite; namespace HelloApp { class Program { static void Main(string[] args) { // метод в качестве параметров получает полный путь к файлу и его название SaveFile("D:\forest.jpg", "Лес"); Console.Read(); } private static void SaveFile(string filename, string title) { // сначала считываем файл из файловой системы // получаем короткое имя файла для сохранения в бд string shortFileName = filename.Substring(filename.LastIndexOf('\\') + 1); // forest.jpg // массив для хранения бинарных данных файла byte[] imageData; using (FileStream fs = new FileStream(filename, FileMode.Open)) { imageData = new byte[fs.Length]; fs.Read(imageData, 0, imageData.Length); } using (var connection = new SqliteConnection("Data Source=filesdata.db")) { connection.Open(); SqliteCommand command = new SqliteCommand(); command.Connection = connection; command.CommandText = @"INSERT INTO Files (Title, FileName, ImageData) VALUES (@FileName, @Title, @ImageData)"; command.Parameters.Add(new SqliteParameter("@FileName", shortFileName)); command.Parameters.Add(new SqliteParameter("@Title", title)); command.Parameters.Add(new SqliteParameter("@ImageData", imageData)); int number = command.ExecuteNonQuery(); Console.WriteLine($"Добавлено объектов: {number}"); } } } }
В данном случае весь код сохранения файла вынесен в отдельный метод SaveFile()
, который в качестве параметров
получает полный путь к файлу и его название. Вначале он считывает данные с помощью класса FileStream в массив байтов. Считанный мссив байтов
собственно и будет представлять данные файла.
using (FileStream fs = new FileStream(filename, FileMode.Open)) { imageData = new byte[fs.Length]; fs.Read(imageData, 0, imageData.Length); }
Затем для сохранения в бд массив байтов передается в строку запроса SQL через один из параметров:
command.Parameters.Add(new SqliteParameter("@ImageData", imageData));
Если после выполнения этой программы мы откроем базу данных через DB Browser for SQLite, то при просмотре добавленной записи мы даже можем увидеть загруженное изображение:
Хотя в данном случае загружается изображение, но это частный случай, в принципе можно использовать и другие типы файлов.
Теперь произведем обратную операцию - получим файл из БД. Вначале определим класс файла, который упростит работу с данными:
public class Image { public Image(int id, string filename, string title, byte[] data) { Id = id; FileName = filename; Title = title; Data = data; } public int Id { get; private set; } public string FileName { get; private set; } public string Title { get; private set; } public byte[] Data { get; private set; } }
Теперь применим этот класс для считывания данных:
using System; using System.Collections.Generic; using System.IO; using Microsoft.Data.Sqlite; namespace HelloApp { class Program { static void Main(string[] args) { GetFiles(); Console.Read(); } private static void GetFiles() { List<Image> images = new List<Image>(); string sql = "SELECT * FROM Files"; using (var connection = new SqliteConnection("Data Source=filesdata.db")) { connection.Open(); SqliteCommand command = new SqliteCommand(sql, connection); using (SqliteDataReader reader = command.ExecuteReader()) { if (reader.HasRows) // если есть данные { while (reader.Read()) // построчно считываем данные { int id = reader.GetInt32(0); string filename = reader.GetString(1); string title = reader.GetString(2); byte[] data = (byte[])reader.GetValue(3); Image image = new Image(id, filename, title, data); images.Add(image); } } Console.WriteLine($"Считано объектов: {images.Count}"); } // для примера сохраним первый файл из списка в папку приложения if (images.Count > 0) { using (FileStream fs = new FileStream(images[0].FileName, FileMode.OpenOrCreate)) { fs.Write(images[0].Data, 0, images[0].Data.Length); Console.WriteLine($"Файл {images[0].Title} сохранен"); } } } } } public class Image { public Image(int id, string filename, string title, byte[] data) { Id = id; FileName = filename; Title = title; Data = data; } public int Id { get; private set; } public string FileName { get; private set; } public string Title { get; private set; } public byte[] Data { get; private set; } } }
Весь код считывания вынесен в отдельный метод GetFiles()
. В данном случае мы считываем все файлы из БД.
Также, как и в общем случае, с помощью объекта SqliteDataReader получаем значения из БД и по ним создаем объект Image, который потом
добавляется в список. Чтобы получить непосредственно данные файла, мы можем просто преобразовать соответствующее значение к массиву байт:
byte[] data = (byte[])reader.GetValue(3);
И в конце смотрим, если в списке есть элементы, то берем первый элемент и сохраняем его на локальный компьютер. И после сохранения в папке нашей программы появится загруженный из базы данных файл.