readallbytes read from example convertir convert bytes arreglo array archivo c# file-io byte

c# - read - Guardando cualquier archivo en la base de datos, simplemente conviértalo en una matriz de bytes?



read binary file c# (7)

¿Qué base de datos estas usando? normalmente no guardas archivos en una base de datos pero creo que sql 2008 tiene soporte para eso ...

Un archivo es datos binarios, por lo tanto, UTF 8 no importa aquí.

UTF 8 es importante cuando intenta convertir una cadena en una matriz de bytes ... no una matriz de archivo a byte.

¿Es la conversión de un archivo a una matriz de bytes la mejor manera de guardar CUALQUIER formato de archivo en el disco o en la columna binaria de la base de datos?

Entonces, si alguien quiere guardar un archivo .gif o .doc / .docx o .pdf, ¿puedo simplemente convertirlo a un bytearray UFT8 y guardarlo en el db como una secuencia de bytes?


Como no se menciona qué base de datos quiere decir, asumo SQL Server. La siguiente solución funciona tanto para 2005 como para 2008.

VARBINARY(MAX) crear una tabla con VARBINARY(MAX) como una de las columnas. En mi ejemplo, he creado Table RaportPlik con la columna RaportPlik siendo la columna VARBINARY(MAX) .

Método para poner el file en la base de datos desde la 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(); } }

Este método es obtener el file de la base de datos y guardarlo en la 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); } } }

Este método es obtener el file de la base de datos y ponerlo como 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; }

Este método es poner MemoryStream en la base de datos:

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; }

Feliz codificación :-)


Confirmando que pude utilizar la respuesta publicada por MadBoy y editada por Otiel en MS SQL Server 2012 y 2014, además de las versiones previamente enumeradas usando columnas varbinary (MAX).

Si se pregunta por qué no puede "Filestream" (indicado en una respuesta separada) como un tipo de datos en el diseñador de tablas SQL Server o por qué no puede establecer el tipo de datos de una columna en "Filestream" utilizando T-SQL, FILESTREAM es un almacenamiento atributo del tipo de datos varbinary (MAX). No es un tipo de datos por sí mismo.

Consulte estos artículos sobre cómo configurar y habilitar FILESTREAM en una base de datos: 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

Una vez configurado, se puede agregar una columna varbinary (max) habilitada para filestream de la siguiente manera:

ALTER TABLE TableName

ADD ColumnName varbinary (max) FILESTREAM NULL

IR


Describiré la forma en que almacené los archivos, en SQL Server y Oracle. En primer lugar, depende de cómo se obtiene el archivo en cuanto a cómo obtendrá sus contenidos, y depende de la base de datos que esté utilizando para el contenido en el que lo almacenará para saber cómo lo almacenará. Estos son 2 ejemplos de bases de datos separadas con 2 métodos separados para obtener el archivo que utilicé.

servidor SQL

Respuesta corta: utilicé una cadena de bytes base64 que convertí en un byte[] y la almacené en un campo varbinary(max) .

Respuesta larga:

Supongamos que está cargando a través de un sitio web, por lo que está utilizando un <input id="myFileControl" type="file" /> control o React DropZone. Para obtener el archivo, estás haciendo algo como var myFile = document.getElementById("myFileControl")[0]; o myFile = this.state.files[0]; .

A partir de ahí, obtendría la cadena base64 usando el código aquí: Convertir entrada = archivo a matriz de bytes (use la función UploadFile2 ).

Luego obtendría esa cadena, el nombre del archivo ( myFile.name ) y el tipo ( myFile.type ) en un objeto JSON:

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

y publique el archivo en un backend del servidor MVC usando XMLHttpRequest, especificando un tipo de contenido de la application/json : xhr.send(JSON.stringify(myJSONObj); Debe construir un ViewModel para vincularlo con:

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

y especifique [FromBody]MyModel myModelObj como parámetro pasado:

[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)

Luego puede agregar esto a esa función y guardarlo usando 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); siendo la línea operativa.

Necesitará un modelo para representar la tabla de la base de datos:

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; } }

Esto guardará los datos en un campo varbinary(max) como un byte[] . Name y el Type fueron nvarchar(250) y nvarchar(10) , respectivamente. Puede incluir el tamaño agregándolo a su tabla como una columna int y MY_ATTACHMENT_TABLE_MODEL como public int Size { get; set;} public int Size { get; set;} , y agregue en la línea tblAtchm.Size = System.Convert.FromBase64String(myModelObj.file).Length; encima.

Oráculo

Respuesta corta: OracleParameter en un byte[] , OracleParameter a OracleParameter , agréguelo a su OracleCommand y actualice el campo BLOB su tabla usando una referencia al valor de ParameterName del ParameterName :BlobParameter

Respuesta larga: cuando hice esto para Oracle, estaba usando un OpenFileDialog y OpenFileDialog y envié la información de bytes / archivo de esta manera:

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); }

Y dentro de la actualización de Oracle, hecho con 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 ); } }

Y el tipo de datos para la columna FILE_CONTENTS era BLOB , el FILE_SIZE era NUMBER(10,0) , LAST_MODIFIED era DATE , y el resto era NVARCHAR2(250) .


Realmente depende del servidor de la base de datos.

Por ejemplo, SQL Server 2008 admite un tipo de datos FILESTREAM para exactamente esta situación.

Aparte de eso, si usa un MemoryStream , tiene un método ToArray() que se convertirá en un byte[] - esto se puede usar para varbinary un campo varbinary .


Sí, generalmente la mejor manera de almacenar un archivo en una base de datos es guardar la matriz de bytes en una columna BLOB. Es probable que desee un par de columnas para almacenar adicionalmente los metadatos del archivo como el nombre, la extensión, etc.

No siempre es una buena idea almacenar archivos en la base de datos; por ejemplo, el tamaño de la base de datos crecerá rápidamente si almacena archivos en él. Pero eso depende de tu escenario de uso.


Si bien puede almacenar archivos de esta manera, tiene importantes ventajas y desventajas:

  • La mayoría de los DB no están optimizados para cantidades gigantes de datos binarios, y el rendimiento de las consultas a menudo se degrada dramáticamente a medida que la tabla se hincha, incluso con índices. (SQL Server 2008, con el tipo de columna FILESTREAM, es la excepción a la regla).
  • La copia de seguridad / replicación de DB se vuelve extremadamente lenta.
  • Es mucho más fácil manejar una unidad corrupta con 2 millones de imágenes, simplemente reemplace el disco en el RAID, que una tabla de base de datos que se corrompe.
  • Si accidentalmente borras una docena de imágenes en un sistema de archivos, tus chicos de operaciones pueden reemplazarlas fácilmente desde una copia de seguridad, y dado que el índice de la tabla es pequeño en comparación, puede restaurarse rápidamente. Si elimina accidentalmente una docena de imágenes en una tabla gigante de bases de datos, tiene una espera larga y dolorosa para restaurar el DB de la copia de seguridad, paralizando todo su sistema mientras tanto.

Estos son solo algunos de los inconvenientes que se me ocurren en la cabeza. Para proyectos pequeños, puede valer la pena almacenar archivos de esta manera, pero si está diseñando un software de nivel empresarial, lo recomendaría encarecidamente.