Cómo guardar archivos en una base de datos
Por Enrique Martínez Montejo
Última revisión: 05/05/2007
 

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

Cómo obtener un objeto Image a partir de un archivo gráfico

Indice de Ejemplos de ADO .NET


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.