none
Como guardar un archivo .PDF en una MySQL con Visual.Net

    Pregunta

  • Buenos días;

    Estoy trabajando en un proyecto con Visual .Net pero necesito guardar un archivo .PDF en una base de datos de MySQL .

    Lo único que he logrado es visualizar el PDF este es el código que tengo:

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles Button1.Click 
            OpenFileDialog2.Filter = "PDF files |*.pdf"
            OpenFileDialog2.InitialDirectory = "C:\Users\ROCIO\Desktop\Archivos"
            OpenFileDialog2.RestoreDirectory = True
            If OpenFileDialog2.ShowDialog = Windows.Forms.DialogResult.OK Then
                AxAcroPDF1.src = OpenFileDialog2.FileName
            End If
        End Sub

    Quisiera guardar en la base el archivo que se muestra en el " AxAcroPDF1.src" para después realizar una búsqueda y que se vuelva a mostrar el archivo pero el que ya este guardado en la base de datos.

    Les agradecería me puedan ayudar.

    jueves, 2 de febrero de 2017 18:01

Respuestas

  • Hola no te recomiendo para nada guardar la ruta del PDF

    Lee el contenido el archivo en formato binario (bytes()) y luego lo almacenas en un campo tipo varbinary(max)

    Dame un email y con gusto te paso un ejemplo.

    Saludos

    jueves, 2 de febrero de 2017 19:04
  • Hola:
    Para el ejemplo, he creado una tabla llamada prueba con la siguiente estructura

    id    int   PK
    pdf   longblob

    En un Form como el de la imagen, copia y pega el siguiente código

    Option Strict On
    Option Explicit On
    Imports System.IO
    Imports MySql.Data.MySqlClient
    Public Class Form1

        Private Sub btnGrabar_Click(sender As Object, e As EventArgs) Handles btnGrabar.Click
            If Me.txtId.Text.Length = 0 Then
                MessageBox.Show("Falta el identificador", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Return
            End If
            If Me.txtPath.Text.Length = 0 Then
                MessageBox.Show("Falta la ruta del Fichero PDF", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Return
            End If

            Dim aBytFichero() As Byte = Nothing
            If Me.txtPath.Text.Length > 0 Then
                aBytFichero = lF_FicheroToByteArray(Me.txtPath.Text)
            End If
            Try
                Dim lsQuery As String = "Insert Into PRUEBA (ID, PDF) Values (@Id, @Pdf)"
                Dim msCadenaMySql = "data source=localhost;user id=root;password='xxxxx';database=TU_BASE_DE_DATOS"

                Using loConexion As New MySqlConnection(msCadenaMySql)
                    ' crear comando
                    Using loComando As New MySqlCommand(lsQuery, loConexion)
                        'añadir parametros al comando
                        loComando.Parameters.Add(New MySqlParameter("@Id", CInt(Me.txtId.Text)))
                        loComando.Parameters.Add(New MySqlParameter("@Pdf", aBytFichero))
                        loConexion.Open()   ' abrir conexión
                        loComando.ExecuteNonQuery()
                    End Using
                End Using
                MessageBox.Show("REGISTRO GRABADO", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Me.txtId.Text = ""
                Me.txtPath.Text = ""
            Catch ex As Exception
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
        End Sub
        Private Sub btnPath_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPath.Click
            Try
                With Me.dlgAbrirArchivo
                    ' Comprobar que el archivo seleccionado existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckFileExists = True
                    ' Comprobar que la ruta de acceso seleccionada existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckPathExists = True
                    ' Obtener o establecer una extensión predeterminada. No incluye el "." inicial.
                    .DefaultExt = "jpg"
                    .Filter = "Ficheros PDF (*.pdf)|*.pdf"
                    .Multiselect = False
                    ' ¿Restaurar el directorio original después de seleccionar un archivo? Si False, el directorio actual cambia al directorio en el que seleccionó el archivo.
                    ' Establézcalo como True para poner la carpeta actual de nuevo donde estaba cuando comenzó.
                    ' El valor predeterminado es False.
                    .RestoreDirectory = True
                    .Title = "Seleccione el Fichero"
                    ' ¿Aceptar sólo nombres de archivo Win32 válidos?
                    .ValidateNames = True
                    If .ShowDialog = Windows.Forms.DialogResult.OK Then
                        Me.txtPath.Text = .FileName
                    End If
                End With
            Catch ex As Exception
                MessageBox.Show(ex.Message, "btnPath_Click", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
        End Sub

        Private Function lF_FicheroToByteArray(ByVal vsFichero As String) As Byte()
            ' abrir el archivo con un objeto stream
            Dim oFileStream As FileStream = New FileStream(vsFichero, FileMode.Open)
            ' crear un array byte que tenga el tamaño del archivo
            Dim aBytImagen() As Byte = New Byte(CInt(oFileStream.Length - 1)) {}
            ' leer con el stream el contenido del archivo y volcarlo al array
            oFileStream.Read(aBytImagen, 0, CInt(oFileStream.Length - 1))
            oFileStream.Close()
            Return aBytImagen
        End Function
    End Class

    P.D.

    Yo tengo por costumbre guardar fichero de cristal (extensión RPT ), documentos, imágenes, etc en campos en vez de tenerlo todo en ficheros y nunca me ha dado problemas.

    Un saludo desde Bilbo
    Carlos

    martes, 7 de febrero de 2017 10:19

Todas las respuestas

  • La recomendacion siempre es guardar solo la ruta en la base de datos para despues abrirla desde la aplicacion

    mira esta es una funcion que utilizo para guadar un archivo en un directorio

    guardandolo con el nombre y la fecha 

    Public Function Archivo()
            'se valida si la variable es un archivo y contiene una extencion valida
            If FUArch.HasFile Then
                Dim validFileTypes As String() = {"pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx"}
                Dim ext As String = System.IO.Path.GetExtension(FUArch.PostedFile.FileName)
                Dim isValidFile As Boolean = False
                For i As Integer = 0 To validFileTypes.Length - 1
                    If ext = "." & validFileTypes(i) Then
                        isValidFile = True
                        'Se crea Folder
                        Dim rut As String
                        rut = rutaDestinoArchivos + Label16.Text
                        CreateFolder(rutaDestinoArchivos, Label16.Text)
                        'Path virtual ()ubicación de la carpeta de imagenes, en donde se guardarán
                        Dim theFileName As String = Path.Combine(Server.MapPath("~/Documentos/Archivos/"), FUArch.FileName)
                        'Se proporciona un nombre nuevo a la imagen, newname contendrá la ruta de imágenes más el archivo.
                        Dim NewName As String = "~/Documentos/Archivos/" + FUArch.FileName
                        ' MsgBox(NewName)
                        'Se declaran variables.
                        Dim ContFileName1, ContFileName2, NewName1, NewName2 As Integer
                        Dim theFileNameNewFront, NewNameFront As String
                        ContFileName1 = theFileName.Length
                        'Se eliminan 5 letras del nombre de la imagen.
                        ContFileName2 = ContFileName1 - 5
                        NewName1 = NewName.Length
                        'se eliminan 5 letras del nombre de la imagen.
                        NewName2 = NewName1 - 5
                        theFileNameNewFront = theFileName.Remove(0, ContFileName2)
                        NewNameFront = NewName.Remove(0, NewName2)
                        Using SQLConn As New SqlConnection(Conn.MyConnString)
                            'Se abre la conexión
                            SQLConn.Open()
                            'Se declara el folio
                            Dim Folio As Integer
                            'Se declara thefilenamenew que es igual al nombre
                            Dim theFileNameNew As String = theFileName
                            theFileNameNew = theFileNameNew.Remove(theFileName.Length - 5)
                            'Se remueven 5 letras del nombre de la imagen
                            NewName = NewName.Remove(NewName.Length - 5)
                            '-------------------------------------------------------------
                            Dim CommandApps As SqlCommand = SQLConn.CreateCommand
                            CommandApps.Connection = SQLConn
                            '-------------------------------------------------------------
                            Select Case x
                                'Se selecciona el case (caso de uso) de acuerdo a la cantidad de archivos, en este caso sería 1
                                Case Is = 1
                                    'Se obtiene el folio desde el filtro donde el id=id
                                    Folio = Consulta.Filtro(3, "").Tables(0).Rows(0)("VAR_ID") + 1
                                    'Al newname se le agrega el folio el -1 más la extension .jpg
                                    'NewName = NewName & Folio & "-1.pdf"
                                    NewName = NewName & Folio & ext
                                    'El filenamenew más folio más -1 con la extension .jpg
                                    'theFileNameNew = theFileNameNew & Folio & "-1.pdf"
                                    theFileNameNew = theFileNameNew & Folio & ext
                                    '-------------------------------------------------------------------------------
                                    'Obtiene el ID del archivo
                                    Dim id As Integer = Consulta.Filtro(3, "").Tables(0).Rows(0)("VAR_ID") + 1
                                    'Obtiene la fecha del día de hoy
                                    Dim fecha As String = Date.Now.ToString("MMddyyyy")
                                    Dim Clave As String
                                    Clave = fecha & id
                                    '-------------------------------------------------------------------------------
                                    'Se declaran las variables necesarias para el update
                                    CommandApps.Parameters.AddWithValue("@VAR_ID", Folio)
                                    CommandApps.Parameters.AddWithValue("@VAR_ARCHIVO", NewName)
                                    '-------------------------------------------------------------------------------
                                    'CommandApps.Parameters.AddWithValue("@VAR_CLAVE", LblClave.Text)
                                    '-------------------------------------------------------------------------------
                                    CommandApps.Parameters.AddWithValue("@VAR_CLAVE", Clave)
                                    'SE INSERTA CON UN 1 CUANDO TIENE EL WHERE
                                    'se realiza el update donde la imagen será cambiada de acuerdo al folio 
                                    '-------------------------------------------------------------------------------
                                    CommandApps.CommandText = "UPDATE SUM_VAR_REY SET VAR_ARCHIVO = @VAR_ARCHIVO WHERE VAR_CLAVE = @VAR_CLAVE"
                                    CommandApps.ExecuteNonQuery()
                            End Select
                            CommandApps.Dispose()
                            'se cierra la conexión
                            SQLConn.Close()
                            'se llena el gridview
                            'LlenarGrid()
                            'se guarda el nombre de la ruta
                            FUArch.SaveAs(theFileNameNew)
                            NameArch = NewName.ToString
                            Exit For
                        End Using
                    Else
                        NameArch = "~/Documentos/Archivos/2-A.jpg"
                    End If
                Next
            Else
                NameArch = "~/Documentos/Archivos/2-A.jpg"
            End If
            Return 0
        End Function

    -Resumiento tendrias que:

    1-Guardar el archivo en el directorio

    2-Guardar en la base de datos LA RUTA

    3-Recuperar el archivo desde LA RUTA 

    4-Mostrarlo en la misma u en otra pagina

    NOTA: La ruta en la que guardes el archivo debe estar compartida para que puedas accesar

    y si quieres cargar archivos de mas de 4 mb tendras que modificar el config.

    jueves, 2 de febrero de 2017 18:22
  • Muchas gracias

    Me parece perfecto solo que se me esta pidiendo que no se guarde la ruta sino el archivo como tal, me pudiera ayudar con alguna otra forma? he leído que se puede convertir a bytes y luego guardar pero no he logrado hacer nada.

    jueves, 2 de febrero de 2017 18:53
  • Hola no te recomiendo para nada guardar la ruta del PDF

    Lee el contenido el archivo en formato binario (bytes()) y luego lo almacenas en un campo tipo varbinary(max)

    Dame un email y con gusto te paso un ejemplo.

    Saludos

    jueves, 2 de febrero de 2017 19:04
  • ingenieria.sc.rociomaya@hotmail.com 

    Es mi correo, gracias.

    jueves, 2 de febrero de 2017 20:07
  • Hola Rocio Maya Camacho,

    Gracias por visitar los foros, preguntarte ¿has podido resolver tu problema?, de ser así, comentarte que sería de gran ayuda para futuros usuarios que visiten los foros el que pudieras compartirnos la forma en la cual resolviste el mismo.

    Saludos

    Joyce

    __________________________________________________________________________________________
    Por favor, recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, hace que sea más fácil para los otros visitantes encontrar la solución  más tarde. Microsoft ofrece este servicio de forma gratuita, con la finalidad de ayudar a los usuarios y la ampliación de la base de datos de conocimientos relacionados con los productos y tecnologías de Microsoft. Este contenido es proporcionado "tal  cual" y no implica ninguna responsabilidad de parte de Microsoft.

    lunes, 6 de febrero de 2017 18:58
    Moderador
  • Hola:
    Para el ejemplo, he creado una tabla llamada prueba con la siguiente estructura

    id    int   PK
    pdf   longblob

    En un Form como el de la imagen, copia y pega el siguiente código

    Option Strict On
    Option Explicit On
    Imports System.IO
    Imports MySql.Data.MySqlClient
    Public Class Form1

        Private Sub btnGrabar_Click(sender As Object, e As EventArgs) Handles btnGrabar.Click
            If Me.txtId.Text.Length = 0 Then
                MessageBox.Show("Falta el identificador", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Return
            End If
            If Me.txtPath.Text.Length = 0 Then
                MessageBox.Show("Falta la ruta del Fichero PDF", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Return
            End If

            Dim aBytFichero() As Byte = Nothing
            If Me.txtPath.Text.Length > 0 Then
                aBytFichero = lF_FicheroToByteArray(Me.txtPath.Text)
            End If
            Try
                Dim lsQuery As String = "Insert Into PRUEBA (ID, PDF) Values (@Id, @Pdf)"
                Dim msCadenaMySql = "data source=localhost;user id=root;password='xxxxx';database=TU_BASE_DE_DATOS"

                Using loConexion As New MySqlConnection(msCadenaMySql)
                    ' crear comando
                    Using loComando As New MySqlCommand(lsQuery, loConexion)
                        'añadir parametros al comando
                        loComando.Parameters.Add(New MySqlParameter("@Id", CInt(Me.txtId.Text)))
                        loComando.Parameters.Add(New MySqlParameter("@Pdf", aBytFichero))
                        loConexion.Open()   ' abrir conexión
                        loComando.ExecuteNonQuery()
                    End Using
                End Using
                MessageBox.Show("REGISTRO GRABADO", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Me.txtId.Text = ""
                Me.txtPath.Text = ""
            Catch ex As Exception
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
        End Sub
        Private Sub btnPath_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPath.Click
            Try
                With Me.dlgAbrirArchivo
                    ' Comprobar que el archivo seleccionado existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckFileExists = True
                    ' Comprobar que la ruta de acceso seleccionada existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckPathExists = True
                    ' Obtener o establecer una extensión predeterminada. No incluye el "." inicial.
                    .DefaultExt = "jpg"
                    .Filter = "Ficheros PDF (*.pdf)|*.pdf"
                    .Multiselect = False
                    ' ¿Restaurar el directorio original después de seleccionar un archivo? Si False, el directorio actual cambia al directorio en el que seleccionó el archivo.
                    ' Establézcalo como True para poner la carpeta actual de nuevo donde estaba cuando comenzó.
                    ' El valor predeterminado es False.
                    .RestoreDirectory = True
                    .Title = "Seleccione el Fichero"
                    ' ¿Aceptar sólo nombres de archivo Win32 válidos?
                    .ValidateNames = True
                    If .ShowDialog = Windows.Forms.DialogResult.OK Then
                        Me.txtPath.Text = .FileName
                    End If
                End With
            Catch ex As Exception
                MessageBox.Show(ex.Message, "btnPath_Click", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
        End Sub

        Private Function lF_FicheroToByteArray(ByVal vsFichero As String) As Byte()
            ' abrir el archivo con un objeto stream
            Dim oFileStream As FileStream = New FileStream(vsFichero, FileMode.Open)
            ' crear un array byte que tenga el tamaño del archivo
            Dim aBytImagen() As Byte = New Byte(CInt(oFileStream.Length - 1)) {}
            ' leer con el stream el contenido del archivo y volcarlo al array
            oFileStream.Read(aBytImagen, 0, CInt(oFileStream.Length - 1))
            oFileStream.Close()
            Return aBytImagen
        End Function
    End Class

    P.D.

    Yo tengo por costumbre guardar fichero de cristal (extensión RPT ), documentos, imágenes, etc en campos en vez de tenerlo todo en ficheros y nunca me ha dado problemas.

    Un saludo desde Bilbo
    Carlos

    martes, 7 de febrero de 2017 10:19
  • Muchas gracias ya solo me faltan los últimos ajustes.
    jueves, 9 de febrero de 2017 21:45
  • Hola:
    Para el ejemplo, he creado una tabla llamada prueba con la siguiente estructura

    id    int   PK
    pdf   longblob

    En un Form como el de la imagen, copia y pega el siguiente código


    Option Strict On
    Option Explicit On
    Imports System.IO
    Imports MySql.Data.MySqlClient
    Public Class Form1

        Private Sub btnGrabar_Click(sender As Object, e As EventArgs) Handles btnGrabar.Click
            If Me.txtId.Text.Length = 0 Then
                MessageBox.Show("Falta el identificador", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Return
            End If
            If Me.txtPath.Text.Length = 0 Then
                MessageBox.Show("Falta la ruta del Fichero PDF", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Return
            End If

            Dim aBytFichero() As Byte = Nothing
            If Me.txtPath.Text.Length > 0 Then
                aBytFichero = lF_FicheroToByteArray(Me.txtPath.Text)
            End If
            Try
                Dim lsQuery As String = "Insert Into PRUEBA (ID, PDF) Values (@Id, @Pdf)"
                Dim msCadenaMySql = "data source=localhost;user id=root;password='xxxxx';database=TU_BASE_DE_DATOS"

                Using loConexion As New MySqlConnection(msCadenaMySql)
                    ' crear comando
                    Using loComando As New MySqlCommand(lsQuery, loConexion)
                        'añadir parametros al comando
                        loComando.Parameters.Add(New MySqlParameter("@Id", CInt(Me.txtId.Text)))
                        loComando.Parameters.Add(New MySqlParameter("@Pdf", aBytFichero))
                        loConexion.Open()   ' abrir conexión
                        loComando.ExecuteNonQuery()
                    End Using
                End Using
                MessageBox.Show("REGISTRO GRABADO", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Me.txtId.Text = ""
                Me.txtPath.Text = ""
            Catch ex As Exception
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
        End Sub
        Private Sub btnPath_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPath.Click
            Try
                With Me.dlgAbrirArchivo
                    ' Comprobar que el archivo seleccionado existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckFileExists = True
                    ' Comprobar que la ruta de acceso seleccionada existe. El cuadro de diálogo muestra una advertencia en caso contrario.
                    .CheckPathExists = True
                    ' Obtener o establecer una extensión predeterminada. No incluye el "." inicial.
                    .DefaultExt = "jpg"
                    .Filter = "Ficheros PDF (*.pdf)|*.pdf"
                    .Multiselect = False
                    ' ¿Restaurar el directorio original después de seleccionar un archivo? Si False, el directorio actual cambia al directorio en el que seleccionó el archivo.
                    ' Establézcalo como True para poner la carpeta actual de nuevo donde estaba cuando comenzó.
                    ' El valor predeterminado es False.
                    .RestoreDirectory = True
                    .Title = "Seleccione el Fichero"
                    ' ¿Aceptar sólo nombres de archivo Win32 válidos?
                    .ValidateNames = True
                    If .ShowDialog = Windows.Forms.DialogResult.OK Then
                        Me.txtPath.Text = .FileName
                    End If
                End With
            Catch ex As Exception
                MessageBox.Show(ex.Message, "btnPath_Click", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
        End Sub

        Private Function lF_FicheroToByteArray(ByVal vsFichero As String) As Byte()
            ' abrir el archivo con un objeto stream
            Dim oFileStream As FileStream = New FileStream(vsFichero, FileMode.Open)
            ' crear un array byte que tenga el tamaño del archivo
            Dim aBytImagen() As Byte = New Byte(CInt(oFileStream.Length - 1)) {}
            ' leer con el stream el contenido del archivo y volcarlo al array
            oFileStream.Read(aBytImagen, 0, CInt(oFileStream.Length - 1))
            oFileStream.Close()
            Return aBytImagen
        End Function
    End Class

    P.D.

    Yo tengo por costumbre guardar fichero de cristal (extensión RPT ), documentos, imágenes, etc en campos en vez de tenerlo todo en ficheros y nunca me ha dado problemas.

    Un saludo desde Bilbo
    Carlos

    Estimado Juan Carlos, me podrias indicar la funcion para hacer todo lo contrario, convertir el campo binario a

    archivo? saludos.

    sábado, 27 de mayo de 2017 5:47
  • Hola:

    Puedes modificar el siguiente codigo par adaptartelo a tu caso

    Option Explicit On
    Option Strict On
    Imports System.IO
    Imports System.Data.SqlClient

    Public Class Form1
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            ' recuperamos el documento de la base de datos y lo pasamos a un fichero
            Try
                Dim aBytDocumento() As Byte = Nothing
                Dim oFileStream As FileStream
                Dim lsQuery As String = "Select CAMPO_BINARIO From TU_TABLA Where ID =@ID"
                Using loConexion As New SqlConnection("TU_CadenaSQL")
                    loConexion.Open()
                    Using loComando As New SqlCommand(lsQuery, loConexion)
                        loComando.Parameters.Add(New SqlParameter("@ID", "EL_VALOR_DEL_ID"))
                        Using loDataReader As SqlDataReader = loComando.ExecuteReader()
                            Do While loDataReader.Read()
                                aBytDocumento = CType(loDataReader("CAMPO_BINARIO"), Byte())
                            Loop
                        End Using
                    End Using
                End Using
                oFileStream = New FileStream("D:\TU_FICHERO.TU_EXTENSION", FileMode.CreateNew, FileAccess.Write)
                oFileStream.Write(aBytDocumento, 0, aBytDocumento.Length)
                oFileStream.Close()
                MessageBox.Show("Documento generado con éxito", "", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End Sub
    End Class

    Un saludo desde Bilbo
    Carlos
    sábado, 27 de mayo de 2017 10:14
  • elmer.fuentes@hotmail.com
    miércoles, 4 de julio de 2018 23:22