Con demasiada frecuencia, los usuarios de los foros de programación suelen recurrir a ellos para preguntar cómo insertar en tiempo de ejecución una imagen, un documento de Word, o cualquier otro archivo, en una base de datos, y con la misma frecuencia, es raro que no se suscite una discusión sobre si es conveniente o no guardar el documento propiamente dicho en la base de datos, o guardar únicamente la ruta a dicho documento.
Desde luego no voy a entrar aquí en discutir qué es lo más conveniente de hacer, por lo que la decisión final la dejaré en manos del usario. No obstante, me siento en la obligación de advertirle, que guardar una imagen o un archivo de Excel, no es lo mismo que guardar un simple campo numérico o alfanumérico, por lo que el tamaño de la base de datos puede sufrir un aumento considerable, cuanto más grande sea el tamaño de los documentos que desee almacenar.
Esto último lo deberá de tener muy en cuenta, sobre todo si el tamaño de la base de datos está limitado, como bien pudiera ser una base de datos Microsoft Access, o aquellas bases de datos SQL Server gestionadas mediante cualquier edición Express de Microsoft SQL Server, por lo que una opción distinta a guardar la ruta del documento, sería limitar en tiempo de ejecución, a un tamaño que estime adecuado, el tamaño máximo de las imágenes que se van a almacenar en la base de datos, a fin de evitar en la medida de lo posible el aumento desmesurado de la base de datos. Dicho esto, mostraré la forma de guardar un documento en una base de datos utilizando código fuente de Visual Basic .net.
En primer lugar, deberá definir en su tabla un campo con el tipo de dato apropiado para guardar una secuencia de bytes. Ello quiere decir que si va a utilizar una base de datos Microsoft Access, el tipo de dato deberá estar definido como Objeto OLE, y como varbinary(max), si el documento se va a guardar en una base de datos Microsoft SQL Server. Tal y como se indica en los Libros en pantalla de SQL Server, el tipo de dato Image, entre otros más, se quitarán en una versión futura de Microsoft SQL Server, por lo que se recomienda que evite su uso en los nuevos diseños de tablas que realice.
Como acabo de indicar, lo que vamos hacer es abrir el documento que deseamos guardar, y crear una secuencia de bytes, que será la que se guarde en el campo de la base de datos. Para ello, nos serviremos de la función que presento a continuación, a la cual sólo deberá de pasarle la ruta del documento que desea guardar, devolviendo un array de bytes como producto de la lectura del archivo.
''' <summary>
''' Devuelve una matriz de bytes con los datos del archivo especificado.
''' </summary>
''' <param name="fileName">Ruta completa del archivo que se desea
leer.</param>
''' <returns></returns>
''' <remarks></remarks>
Private Shared Function ReadBinaryFile(ByVal
fileName As String)
As Byte()
' Generar una excepción si no
existe el archivo.
'
If (Not
IO.File.Exists(fileName)) Then
Throw New
IO.FileNotFoundException("No existe el archivo especificado.")
End If
' Leer el archivo especificado devolviendo una matriz de
bytes con su contenido.
'
Return IO.File.ReadAllBytes(fileName)
End Function
Cómo leer una secuencia de bytes
Ahora expondré un ejemplo para añadir una nueva fila a una tabla de una base de datos de SQL Server, por lo que necesariamente deberá de haber definido una columna con el tipo de dato varbinary(max), que será el que almacenará un documento de Microsoft Word.
Private Sub
Button1_Click(sender As Object, e As
EventArgs) Handles Button1.Click
Try
' Leer el archivo binario
especificado en el control TextBox.
'
Dim blob As Byte() =
ReadBinaryFile(TextBox1.Text)
'
Establecemos una conexión para conectarnos
' a la base de datos de SQL Server,
utilizando
' la seguridad integrada de Windows
NT.
'
Using
cnn As New SqlConnection("Data
Source=(local);" & _
"Initial Catalog=NombreBaseSQLServer;" & _
"Integrated Security=SSPI")
Dim cmd As
SqlCommand = cnn.CreateCommand()
' Crear la
consulta T-SQL para insertar un nuevo registro.
'
cmd.CommandText = "INSERT INTO Documentos (IdBlob, CampoBlob) VALUES (@id,
@blob)"
' Añadir el único parámetro de entrada existente.
'
cmd.Parameters.AddWithValue("@id", Convert.ToInt32(txtIdBlob.Text))
' La función ReadBinaryFile tal cual se encuentra implementada no devolverá
un valor Nothing,
' pero
muestro cómo especificar un valor NULL al parámetro de entrada si el valor del campo
' binario
fuese Nothing. Para insertar un valor NULL, el campo de la tabla lo tiene
que permitir.
'
cmd.Parameters.AddWithValue("@blob",
If(blob IsNot Nothing, blob, CObj(DBNull.Value)))
cnn.Open()
Dim n As
Integer = cmd.ExecuteNonQuery()
If (n > 0)
Then
MessageBox.Show("Se ha grabado el documento satisfactoriamente.")
Else
MessageBox.Show("No se ha guardado ningún documento.")
End If
End Using
Catch ex
As Exception
' Se ha producido un error.
MessageBox.Show(ex.Message)
End Try
End Sub
Otros enlaces de interés:
Cómo leer los archivos contenidos en una base de datos
Enrique Martínez Montejo - 2007
NOTA: La información contenida en este artículo, así como el código fuente incluido en el mismo, se proporciona COMO ESTÁ, sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo explicado, recomendado o sugerido en el presente artículo.
NOTE: The information contained in this article and source code included therein, is provided AS IS without warranty of any kind, and confers no rights. You assume any risk to implement, use or run it explained, recommended or suggested in this article.