Сохранение любого файла в базе данных, просто преобразование его в массив байтов?

Преобразует ли файл в массив байтов лучший способ сохранить ЛЮБОЙ формат файла на диске или двоичном столбце базы данных var?

Итак, если кто-то хочет сохранить файл .gif или .doc / .docx или .pdf, могу ли я просто преобразовать его в bytearray UFT8 и сохранить его в db как stream байтов?

Поскольку не упоминается, какая firebase database вы имеете в виду, я предполагаю SQL Server. Ниже решения работает как в 2005, так и в 2008 году.

Вы должны создать таблицу с VARBINARY(MAX) качестве одного из столбцов. В моем примере я создал Table Raporty со столбцом RaportPlik являющимся VARBINARY(MAX) .

Способ поместить file в базу данных с drive :

 public static void databaseFilePut(string varFilePath) { byte[] file; using (var stream = new FileStream(varFilePath, FileMode.Open, FileAccess.Read)) { using (var reader = new BinaryReader(stream)) { file = reader.ReadBytes((int) stream.Length); } } using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) using (var sqlWrite = new SqlCommand("INSERT INTO Raporty (RaportPlik) Values(@File)", varConnection)) { sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file; sqlWrite.ExecuteNonQuery(); } } 

Этот метод состоит в том, чтобы получить file из базы данных и сохранить его на drive :

 public static void databaseFileRead(string varID, string varPathToNewLocation) { using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) { sqlQuery.Parameters.AddWithValue("@varID", varID); using (var sqlQueryResult = sqlQuery.ExecuteReader()) if (sqlQueryResult != null) { sqlQueryResult.Read(); var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))]; sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length); using (var fs = new FileStream(varPathToNewLocation, FileMode.Create, FileAccess.Write)) fs.Write(blob, 0, blob.Length); } } } 

Этот метод состоит в том, чтобы получить file из базы данных и поместить его как MemoryStream :

 public static MemoryStream databaseFileRead(string varID) { MemoryStream memoryStream = new MemoryStream(); using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) { sqlQuery.Parameters.AddWithValue("@varID", varID); using (var sqlQueryResult = sqlQuery.ExecuteReader()) if (sqlQueryResult != null) { sqlQueryResult.Read(); var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))]; sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length); //using (var fs = new MemoryStream(memoryStream, FileMode.Create, FileAccess.Write)) { memoryStream.Write(blob, 0, blob.Length); //} } } return memoryStream; } 

Этот метод заключается в том, чтобы поместить MemoryStream в базу данных:

 public static int databaseFilePut(MemoryStream fileToPut) { int varID = 0; byte[] file = fileToPut.ToArray(); const string preparedCommand = @" INSERT INTO [dbo].[Raporty] ([RaportPlik]) VALUES (@File) SELECT [RaportID] FROM [dbo].[Raporty] WHERE [RaportID] = SCOPE_IDENTITY() "; using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) { sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file; using (var sqlWriteQuery = sqlWrite.ExecuteReader()) while (sqlWriteQuery != null && sqlWriteQuery.Read()) { varID = sqlWriteQuery["RaportID"] is int ? (int) sqlWriteQuery["RaportID"] : 0; } } return varID; } 

Счастливое кодирование 🙂

Хотя вы можете хранить файлы таким образом, у этого есть значительные компромиссы:

  • Большинство БД не оптимизированы для гигантских количеств двоичных данных, и производительность запросов часто резко ухудшается, поскольку таблица раздувается даже с индексами. (SQL Server 2008 с типом столбца FILESTREAM является исключением из правила).
  • Резервное копирование / репликация БД происходит очень медленно.
  • Гораздо проще обрабатывать поврежденный диск с 2 миллионами изображений – просто замените диск на RAID – таблицу DB, которая становится поврежденной.
  • Если вы случайно удалите дюжину изображений в файловой системе, ваши ребята могут легко заменить их из резервной копии, а так как индекс таблицы крошечный по сравнению, его можно быстро восстановить. Если вы случайно удалите дюжину изображений в таблице гигантских баз данных, у вас будет долгое и мучительное ожидание восстановления БД из резервной копии, парализуя всю вашу систему тем временем.

Это лишь некоторые из недостатков, которые я могу придумать с головы. Для крошечных проектов, возможно, стоит хранить файлы таким образом, но если вы разрабатываете программное обеспечение корпоративного уровня, я бы настоятельно рекомендовал против него.

Это действительно зависит от сервера базы данных.

Например, SQL Server 2008 поддерживает тип данных FILESTREAM для этой ситуации.

Помимо этого, если вы используете MemoryStream , у него есть метод ToArray() который будет преобразовывать в byte[] – это можно использовать для varbinary поля varbinary .

Подтвердив, что я смог использовать ответ, отправленный MadBoy, и отредактировал Otiel как на MS SQL Server 2012, так и на 2014 год в дополнение к версиям, ранее перечисленным с использованием столбцов varbinary (MAX).

Если вам интересно, почему вы не можете «Filestream» (отмеченный в отдельном ответе) как тип данных в дизайнере таблиц SQL Server или почему вы не можете установить тип данных столбца на «Filestream» с помощью T-SQL, это связано с тем, что FILESTREAM является хранилищем атрибут типа данных varbinary (MAX). Это не тип данных.

См. Эти статьи по настройке и включению FILESTREAM в базе данных: https://msdn.microsoft.com/en-us/library/cc645923(v=sql.120).aspx

http://www.kodyaz.com/t-sql/default-filestream-filegroup-is-not-available-in-database.aspx

После настройки можно включить добавочный столбец varminary (max), который может быть добавлен в stream:

ALTER TABLE Имя таблицы

ADD ColumnName varbinary (max) FILESTREAM NULL

ИДТИ

Какую базу данных вы используете? обычно вы не сохраняете файлы в базе данных, но я думаю, что sql 2008 поддерживает его …

Файл представляет собой двоичные данные, поэтому UTF 8 здесь не имеет значения.

UTF 8 имеет значение, когда вы пытаетесь преобразовать строку в массив байтов … не файл в массив байтов.

Я опишу способ хранения файлов в SQL Server и Oracle. Это во многом зависит от того, как вы получаете файл, в первую очередь, о том, как вы получите его содержимое, и зависит от того, какую базу данных вы используете для контента, в котором вы будете хранить его, для того, как вы его сохраните. Это два отдельных примера базы данных с двумя отдельными способами получения файла, который я использовал.

SQL Server

Короткий ответ: я использовал строку байта base64, которую я преобразовал в byte[] и сохранил в поле varbinary(max) .

Длительный ответ:

Скажем, что вы загружаете веб-сайт, поэтому вы используете или React DropZone. Чтобы получить файл, вы делаете что-то вроде var myFile = document.getElementById("myFileControl")[0]; или myFile = this.state.files[0]; ,

Оттуда я бы получил строку base64, используя здесь код: Преобразование input = file в массив байтов (используйте функцию UploadFile2 ).

Тогда я бы получил эту строку, имя файла ( myFile.name ) и тип ( myFile.type ) в объект JSON:

 var myJSONObj = { file: base64string, name: myFile.name, type: myFile.type, } 

и xhr.send(JSON.stringify(myJSONObj); файл на серверный сервер MVC с использованием XMLHttpRequest, указав Content-Type of application/json : xhr.send(JSON.stringify(myJSONObj); вам нужно создать ViewModel, чтобы связать его с:

 public class MyModel { public string file { get; set; } public string title { get; set; } public string type { get; set; } } 

и укажите [FromBody]MyModel myModelObj как переданный в параметре:

 [System.Web.Http.HttpPost] // required to spell it out like this if using ApiController, or it will default to System.Mvc.Http.HttpPost public virtual ActionResult Post([FromBody]MyModel myModelObj) 

Затем вы можете добавить это в эту функцию и сохранить ее с помощью Entity Framework:

 MY_ATTACHMENT_TABLE_MODEL tblAtchm = new MY_ATTACHMENT_TABLE_MODEL(); tblAtchm.Name = myModelObj.name; tblAtchm.Type = myModelObj.type; tblAtchm.File = System.Convert.FromBase64String(myModelObj.file); EntityFrameworkContextName ef = new EntityFrameworkContextName(); ef.MY_ATTACHMENT_TABLE_MODEL.Add(tblAtchm); ef.SaveChanges(); 

tblAtchm.File = System.Convert.FromBase64String(myModelObj.file); являясь оперативной линией.

Для представления таблицы базы данных вам понадобится модель:

 public class MY_ATTACHMENT_TABLE_MODEL { [Key] public byte[] File { get; set; } // notice this change public string Name { get; set; } public string Type { get; set; } } 

Это сохранит данные в поле varbinary(max) в виде byte[] . Name и Type были соответственно nvarchar(250) и nvarchar(10) . Вы можете включить размер, добавив его в свою таблицу в качестве столбца int & MY_ATTACHMENT_TABLE_MODEL как public int Size { get; set;} public int Size { get; set;} и добавить строку tblAtchm.Size = System.Convert.FromBase64String(myModelObj.file).Length; выше.

oracle

Короткий ответ: преобразуйте его в byte[] , назначьте его в OracleParameter , добавьте его в свой OracleCommand и обновите поле BLOB вашей таблицы, используя ссылку на значение параметра ParameterName :BlobParameter

Длинный ответ: когда я сделал это для Oracle, я использовал OpenFileDialog и я получил и отправил информацию о байтах / файлах таким образом:

 byte[] array; OracleParameter param = new OracleParameter(); Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog(); dlg.Filter = "Image Files (*.jpg, *.jpeg, *.jpe)|*.jpg;*.jpeg;*.jpe|Document Files (*.doc, *.docx, *.pdf)|*.doc;*.docx;*.pdf" if (dlg.ShowDialog().Value == true) { string fileName = dlg.FileName; using (FileStream fs = File.OpenRead(fileName) { array = new byte[fs.Length]; using (BinaryReader binReader = new BinaryReader(fs)) { array = binReader.ReadBytes((int)fs.Length); } // Create an OracleParameter to transmit the Blob param.OracleDbType = OracleDbType.Blob; param.ParameterName = "BlobParameter"; param.Value = array; // <-- file bytes are here } fileName = fileName.Split('\\')[fileName.Split('\\').Length-1]; // gets last segment of the whole path to just get the name string fileType = fileName.Split('.')[1]; if (fileType == "doc" || fileType == "docx" || fileType == "pdf") fileType = "application\\" + fileType; else fileType = "image\\" + fileType; // SQL string containing reference to BlobParameter named above string sql = String.Format("INSERT INTO YOUR_TABLE (FILE_NAME, FILE_TYPE, FILE_SIZE, FILE_CONTENTS, LAST_MODIFIED) VALUES ('{0}','{1}',{2},:BlobParamerter, SYSDATE)", fileName, fileType, array.Length); // Do Oracle Update RunCommand(sql, param); } 

И внутри обновления Oracle, выполненного с помощью ADO:

 public void RunCommand(string sql, OracleParameter param) { OracleConnection oraConn = null; OracleCommand oraCmd = null; try { string connString = GetConnString(); oraConn = OracleConnection(connString); using (oraConn) { if (OraConnection.State == ConnectionState.Open) OraConnection.Close(); OraConnection.Open(); oraCmd = new OracleCommand(strSQL, oraConnection); // Add your OracleParameter if (param != null) OraCommand.Parameters.Add(param); // Execute the command OraCommand.ExecuteNonQuery(); } } catch (OracleException err) { // handle exception } finally { OraConnction.Close(); } } private string GetConnString() { string host = System.Configuration.ConfigurationManager.AppSettings["host"].ToString(); string port = System.Configuration.ConfigurationManager.AppSettings["port"].ToString(); string serviceName = System.Configuration.ConfigurationManager.AppSettings["svcName"].ToString(); string schemaName = System.Configuration.ConfigurationManager.AppSettings["schemaName"].ToString(); string pword = System.Configuration.ConfigurationManager.AppSettings["pword"].ToString(); // hopefully encrypted if (String.IsNullOrEmpty(host) || String.IsNullOrEmpty(port) || String.IsNullOrEmpty(serviceName) || String.IsNullOrEmpty(schemaName) || String.IsNullOrEmpty(pword)) { return "Missing Param"; } else { pword = decodePassword(pword); // decrypt here return String.Format( "Data Source=(DESCRIPTION =(ADDRESS = ( PROTOCOL = TCP)(HOST = {2})(PORT = {3}))(CONNECT_DATA =(SID = {4})));User Id={0};Password{1};", user, pword, host, port, serviceName ); } } 

И тип данных для столбца FILE_CONTENTS был BLOB , FILE_SIZE - NUMBER(10,0) , LAST_MODIFIED - DATE , а остальное - NVARCHAR2(250) .

Да, обычно лучший способ сохранить файл в базе данных – сохранить массив байтов в столбце BLOB. Вероятно, вам понадобится несколько столбцов для дополнительного хранения метаданных файла, таких как имя, расширение и т. Д.

Не всегда хорошая идея хранить файлы в базе данных – например, размер базы данных будет быстро расти, если вы храните в нем файлы. Но все зависит от вашего сценария использования.

  • Есть ли Java API для файлов mp4?
  • Модульный ввод / вывод файлов
  • проверка для eof в строке :: getline
  • Как использовать Java для чтения из файла, который активно записывается?
  • Прямая косая черта или обратная косая черта?
  • Чтение строки из файла без знания длины строки
  • Проверка строки для непечатаемых символов при чтении текстового файла
  • Запись в консольный и текстовый файл
  • C ++ / Win32: Как дождаться завершения отложенного удаления?
  • Как проверить, существует ли файл на Java?
  • Как читать содержимое каталога в Perl?
  • Давайте будем гением компьютера.