Access - Insertar adjunto en postgreSQL y Access

 
Vista:

Insertar adjunto en postgreSQL y Access

Publicado por BMOTheGolem (8 intervenciones) el 24/01/2024 09:12:27
Buenas, tengo un problema, en access, en una tabla vinculada a postgresql, en archivos adjuntos, si inserto un archivo, se elimina el registro. Alguien sabe por que es? Gracias, el formato del campo es BYTEA
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Insertar adjunto en postgreSQL y Access

Publicado por Eduardo Pérez Fernández (317 intervenciones) el 24/01/2024 14:13:45
Sin conocer el código que está utilizando no es posible dar un concepto. Personalmente no utilizo tablas vinculadas y el manejo de subir y descargar archivos almacenados en campo bytea lo hago con una clase. Le dejo los 2 métodos de la clase (Hay otra forma)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
Public Function SubirImagen(ByVal tableName As String, ByVal fieldName As String, ByVal imagePath As String, ByVal conditionField As String, ByVal conditionValue As String) As Boolean
 
'Método para subir una imagen al servidor de PostgreSQL
'Parámetros:
'            tablename ----- > Nombre de la tabla en PostgreSQL en la sentencia SQL
'            fieldName ----- > Nombre del campo bytea en PostgreSQL
'            imagePath ----- > Ruta y nombre del archivo de la imagen a subir
'            conditionField  > Nombre del campo del id, por ejemplo, idempleado
'            conditionValue  > Valor del ID, por ejemplo si el idempleado=3 seria 3
'Ejemplo de llamada:
'
 
' NOTA:
 
'La función   utiliza parámetros SQL para realizar la inserción y actualización directamente en la base de datos PostgreSQL.
'La función DiscoAOle()  lee el contenido binario del archivo y luego actualiza cada registro en el conjunto de resultados ADO con el contenido binario.
'En consecuencia esta función es más rápida o eficiente
 
    On Error GoTo ErrorHandler
 
    ' Variable booleana para rastrear errores
    Dim success As Boolean
    success = True
 
    ' Crear un objeto ADODB.Stream
    Dim objStream As Object
    Set objStream = CreateObject("ADODB.Stream")
 
    ' Especificar el tipo del Stream (adTypeBinary para datos binarios)
    objStream.Type = 1 ' adTypeBinary
 
    ' Abrir el Stream
    objStream.Open
 
    ' Leer la imagen desde un archivo
    objStream.LoadFromFile imagePath
 
    ' Crear un objeto de comando ADO
    Dim objCommand As Object
    Set objCommand = CreateObject("ADODB.Command")
 
    ' Especificar el SQL para la actualización de datos
    Dim strSQL As String
    strSQL = "UPDATE " & tableName & " SET " & fieldName & " = ? WHERE " & conditionField & " = ?"
 
    ' Configurar el comando
    objCommand.ActiveConnection = conn
    objCommand.CommandText = strSQL
 
    ' Agregar el primer parámetro de imagen al comando
    Dim objParameter1 As Object
    Set objParameter1 = objCommand.CreateParameter(fieldName, 205, 1, -1, objStream.Read)
    objCommand.Parameters.Append objParameter1
 
    ' Agregar el segundo parámetro de condición al comando
    Dim objParameter2 As Object
    Set objParameter2 = objCommand.CreateParameter(conditionField, adVarChar, adParamInput, Len(conditionValue), conditionValue)
    objCommand.Parameters.Append objParameter2
 
    ' Ejecutar el comando (realizar la actualización)
    objCommand.Execute
 
    ' Cerrar y liberar recursos
    objStream.Close
    Set objStream = Nothing
    Set objCommand = Nothing
 
    ' Devolver el resultado
    SubirImagen = success
    Exit Function
 
ErrorHandler:
    Debug.Print "Error al actualizar imagen: " & Err.Description
    ' Si se produce un error, establecer el resultado en False
    success = False
    SubirImagen = success
End Function
 
Public Function DescargarImagen(ByVal tableName As String, ByVal fieldName As String, ByVal conditionField As String, ByVal conditionValue As String, ByVal outputPath As String) As Boolean
    On Error GoTo ErrorHandler
 
    ' Variable booleana para rastrear errores
    Dim success As Boolean
    success = True
 
    ' Crear un objeto de comando ADO
    Dim objCommand As Object
    Set objCommand = CreateObject("ADODB.Command")
 
    ' Especificar el SQL para la selección de datos
    Dim strSQL As String
    strSQL = "SELECT " & fieldName & " FROM " & tableName & " WHERE " & conditionField & " = ?"
 
    ' Configurar el comando
    objCommand.ActiveConnection = conn
    objCommand.CommandText = strSQL
 
    ' Agregar el parámetro de condición al comando
    Dim objParameter As Object
    Set objParameter = objCommand.CreateParameter(conditionField, adVarChar, adParamInput, Len(conditionValue), conditionValue)
    objCommand.Parameters.Append objParameter
 
    ' Abrir un Recordset con la imagen
    Set rs = objCommand.Execute
 
    ' Verificar si se encontraron resultados
    If Not rs.EOF Then
        ' Crear un objeto ADODB.Stream para la imagen
        Dim objStream As Object
        Set objStream = CreateObject("ADODB.Stream")
 
        ' Especificar el tipo del Stream (adTypeBinary para datos binarios)
        objStream.Type = 1 ' adTypeBinary
 
        ' Abrir el Stream
        objStream.Open
 
        ' Copiar el contenido del campo bytea al Stream
        objStream.Write rs.Fields(fieldName).Value
 
        ' Guardar la imagen en disco
        objStream.SaveToFile outputPath, 2 ' adSaveCreateOverWrite
 
        ' Cerrar el Stream
        objStream.Close
    Else
        Debug.Print "No se encontró la imagen para la condición especificada."
        success = False
    End If
 
    ' Cerrar y liberar recursos
    rs.Close
    Set rs = Nothing
    Set objCommand = Nothing
 
    ' Devolver el resultado
    DescargarImagen = success
    Exit Function
 
ErrorHandler:
    Debug.Print "Error al descargar imagen: " & Err.Description
    ' Si se produce un error, establecer el resultado en False
    success = False
    DescargarImagen = success
End Function
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Insertar adjunto en postgreSQL y Access

Publicado por Eduardo Pérez Fernández (317 intervenciones) el 24/01/2024 14:43:07
Le dejo la otra forma, Debe crear la conexión con el servidor, en este caso la clase la guarda en la variable conn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
Public Function OleADisco(ByVal tabla As String, ByVal id As Long, ByVal campoOLE As String, ByVal nombreArchivo As String, ByVal campoWhere As String, Optional Tipo As Byte) As String
 
'Referenciar  Microsoft ActiveX Data Objects x.x Library
'En este código actualizado, se utiliza un objeto ADODB.Stream para leer los datos del campo bytea.
'Los datos se escriben en el Stream y luego se leen en el arreglo de bytes Matrix.
'Esto para evitar error 13 no coinciden los tipos cuando el campo bytea esta vacío.
 
    Dim rst As New ADODB.Recordset
    Dim sql, Ruta As String
    Dim Matrix() As Byte
    Dim NumArchivo As Byte
    Dim conexion As Variant
 
     On Error GoTo ManipularError
 
    ' Verificar si la conexión está abierta
    conexion = OpenConnection()
 
    sql = "SELECT * FROM " & tabla & " WHERE " & campoWhere & " = " & id
 
    rst.Open sql, conn, adOpenForwardOnly, adLockReadOnly
 
    With rst
        NumArchivo = FreeFile
        Ruta = CurrentProject.Path & "\" & nombreArchivo
 
        If Not IsNull(.Fields(campoOLE).Value) Then
            If LenB(.Fields(campoOLE).Value) > 0 Then
                Dim Stream As Object
                Set Stream = CreateObject("ADODB.Stream")
                Stream.Type = adTypeBinary
                Stream.Open
                Stream.Write .Fields(campoOLE).Value
                Stream.Position = 0
                Matrix = Stream.Read
                Stream.Close
            Else
                OleADisco = ""
                Exit Function
            End If
        Else
            OleADisco = ""
            Exit Function
        End If
    End With
 
    rst.Close: Set rst = Nothing
    Open Ruta For Binary Access Write As #NumArchivo
    Put #NumArchivo, 1, Matrix
    Close #NumArchivo
    OleADisco = Ruta
 
    ' conn.Close 'Si la activo se oculta el formulario imagenes
 
    Exit Function
 
ManipularError:
    If Not rst Is Nothing Then rst.Close: Set rst = Nothing
    MsgBox Err.Number & "Error al descargar la imagen" & vbCrLf & vbCrLf & Err.Description, vbCritical, "Atención"
    Resume Next
    Exit Function
End Function
Public Function DiscoAOle(ByVal tabla As String, ByVal id As Long, ByVal campoOLE As String, ByVal nombreArchivo As String, ByVal campoWhere As String, Optional Tipo As Byte) As Boolean
 
    Dim rst As New ADODB.Recordset
    Dim sql As String, Ruta As String
    Dim NumArchivo As Byte, Aux As Boolean
    Dim Matrix() As Byte
    Dim conexion As Variant
 
    On Error GoTo ManipularError
 
    ' Verificar si la conexión está abierta
    conexion = OpenConnection()
 
    If Tipo = 1 Then
        sql = "SELECT * FROM " & tabla
    Else
        sql = "SELECT * FROM " & tabla & " WHERE " & campoWhere & "=" & id
    End If
 
    rst.Open sql, conn, adOpenDynamic, adLockOptimistic
 
    NumArchivo = FreeFile
    Ruta = nombreArchivo
    Aux = True: Open Ruta For Binary Access Read As #NumArchivo
    ReDim Matrix(LOF(NumArchivo) - 1)
    Get #NumArchivo, , Matrix
    Close #NumArchivo: Aux = False
 
    With rst
        If Not .BOF And Not .EOF Then
            .MoveFirst
            Do While Not .EOF
                .Fields(campoOLE).Value = Matrix
                .Update
                .MoveNext
            Loop
        End If
    End With
 
    rst.Close
    'conn.Close  'Si se cierra se oculta el formulario imagenes
 
    If Tipo = 1 Then
        MsgBox "Registro agregado correctamente.", vbInformation, "Aviso"
    Else
'        MsgBox "Registro editado correctamente.", vbInformation, "Aviso"
    End If
 
    DiscoAOle = True
 
Exit Function
 
ManipularError:
    If Aux Then: Close #NumArchivo
    MsgBox Err.Number & "Error al descargar la imagen" & vbCrLf & vbCrLf & Err.Description, vbCritical, "Atención"
    Exit Function
 
End Function
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Insertar adjunto en postgreSQL y Access

Publicado por BMOTheGolem (8 intervenciones) el 25/01/2024 10:27:35
Buenas Eduardo, muchas gracias por su comentario, realmente no se eliminaba el registro, simplemente se movia al final de todo, el sistema actual que uso para adjuntar objetos es con un suformulario en vista hoja de datos con los campos para adjuntar, pero siempre aparece el texto "Objeto OLE" y no se diferencia cando el campo esta vacio y cuando no, ademas, para importar un archivo se hace con clic derecho: insertar objeto, no es tan intuitivo para el usuario. Podria decirme, a parte del codigo, que le agradezco y implementare en breves, que sistema usa para identificar si el campo esta vacio o no? Ademas, como podria hacer que este sistema se use en varias tablas y que identifique la tabla y campos automaticamente, o no es posible? Gracias Eduardo por su tiempo
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Insertar adjunto en postgreSQL y Access

Publicado por Eduardo Pérez Fernández (317 intervenciones) el 25/01/2024 13:56:52
No puede utilizar directamente un campo BYTEA en tablas vinculadas, el campo se debe descargar a disco y de esta forma manipularlo, si es imagen o un archivo de texto, Excel etc. Puede utilizar esta función de PostrgreSQL para determinar si un campo BYTEA esta vacío.

1
2
3
4
5
6
7
8
9
10
11
CREATE OR REPLACE FUNCTION es_bytea_vacio(nombre_tabla text, nombre_campo_bytea text, nombre_campo_id text, valor_id INT)
RETURNS BOOLEAN AS $$
DECLARE
    campo_vacio BOOLEAN;
BEGIN
    EXECUTE 'SELECT COALESCE(LENGTH(' || quote_ident(nombre_campo_bytea) || '), 0) = 0 FROM ' || quote_ident(nombre_tabla) || ' WHERE ' || quote_ident(nombre_campo_id) || ' = $1' INTO campo_vacio
    USING valor_id;
 
    RETURN campo_vacio;
END;
$$ LANGUAGE plpgsql;

Ejemplo de llamada de la función.

1
2
-- Llamando a la función para comprobar si el campo bytea 'mi_campo_bytea' en la tabla 'mi_tabla' para el idimagen 1 está vacío
SELECT es_bytea_vacio('mi_tabla', 'mi_campo_bytea', 'idimagen', 1);

En donde :
mi_tabla es el nombre de la tabla
mi_campo_byeta es el nombre del campo BYTEA
idmagen es el nombre del campo id
1 es valor del id

No obstante la funciones que le suministré controlan si el contenido del campo BYETA es NULL, por ejemplo,

If Not IsNull(.Fields(campoOLE).Value) Then

Observe pr ejemplo la función OleADisco() Si el campo BYTEA no tiene datos retorna una cadena vacía, en caso contrario lo almacena en en disco y retorna la ruta, de tal forma que ésta se indica como origne de datos del control que muestra la imagen.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Insertar adjunto en postgreSQL y Access

Publicado por BMOTheGolem (8 intervenciones) el 26/01/2024 09:51:25
Muchas gracias Eduardo, lo implementare dentro de poco, le agradezco mucho su colaboracion.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Insertar adjunto en postgreSQL y Access

Publicado por Eduardo Pérez Fernández (317 intervenciones) el 26/01/2024 13:45:10
Con gusto, le recomiendo haga un curso de PostgreSQL avanzado.

Un saludo desde Colombia
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar