Imprimir página | Cerrar ventana

Subir archivos por vba a la nube con dropbox

Impreso de: Foro de Access y VBA
Categoría: Access y VBA
Nombre del foro: Access y VBA
Descripción del foro: Foro de programacion en Access (Con código y sin código)
URL: http://www.mvp-access.com/foro/forum_posts.asp?TID=84478
Fecha de impresión: 21/Julio/2019 a las 07:00


Tema: Subir archivos por vba a la nube con dropbox
Publicado por: rokoko
Asunto: Subir archivos por vba a la nube con dropbox
Fecha de publicación: 04/Mayo/2019 a las 13:57
Buenas!!

Hace un tiempo abri un hilo sobre este tema pero no llegue a ningun lado, parece que no habia gente que utilizase este metodo, cosa que me parece muy practica y segura, subir archivos a dropbox sin tenerlo instalado en el pc.

El objetivo seria este, subir archivos(copias seguridad de tablas) a dropbox silenciosamente al cerrar la aplicacion. Pongo dropbox porque es del que he encontrado informacion, pero podria ser drive o mega.....

El escenario es este, de hay que quiera hacerlo asi en parte. Son ordenadores que estan capados, no se les puede instalar nada. Todos los usuarios tienen su cuenta en el dominio, aunque se pudiese instalar dropbox(que no se puede) habria que crear la cuenta dropbox en todos los usuarios......

He encontrado esta info con APIs de dropbox. Parece que si se puede hacer lo que quiero.

https://veroniquefrizzell.com/using-vba-with-dropbox-api/

https://www.dropbox.com/developers-v1/core/docs#files_put

https://www.dropbox.com/developers

En el primer enlace hay un ejemplo de VBA pero que no llego a comprender bien o esta poco desarrolado....

A ver si alguien le saca jugo a esto, que creo es bien practico..

Saludos







Respuestas:
Publicado por: guarracuco
Fecha de publicación: 06/Mayo/2019 a las 14:51
El primer enlace utiliza el recurso para listar los usuarios que tienen acceso a las carpetas compartidas.

En esa misma lista de recursos o endpoints, ubica alguna que haga referencia a put o upload files.
Hay dos maneras de conectarse con las APIs: conexion directa o utilizando aplicaciones de terceros o OAuth2 que es un tanto complicado.
El ejemplo muestra la directa: token.

OAuth2:
Aplicaciones de terceros es cuando un desarrollador crea una aplicacion para que cualquier otro usuario del mismo servicio pueda utilizarlo. Es decir, tu aplicacion es un intermediario entre el usuario y el servicio (Dropbox, Square, Mailchimp y un largo etc). Cuando un usuario lo va a utilizar, es direccionado a la pagina oficial (como lo viene haciendo desde hace mas de una decada Paypal) para conectarse y autorizar que esa aplicacion tendra acceso a ciertas secciones de tu cuenta.
Si el acceso es permitido, se genera un token temporal con el cual el usuario hace peticiones al servicio: dame esta lista, actualiza este registro, etc.
No lo probe pero no hay duda de que desde VBA lo puedes hacer. Yo vengo haciendolo con Square y otros metodos de pago, MailChimp, WordPress, Twilio.

Actualiza los siguientes valores:
1) myurl = UBICA EL ENDPOINT PARA ENVIAR ARCHIVOS
2) argumentString
3) your-access-token

y por supuesto, primero crea tu aplicacion en tu cuenta de DropBox.



-------------
https://tucondominioaldia.net


Publicado por: rokoko
Fecha de publicación: 07/Mayo/2019 a las 17:38
Algun pequeño avance he hecho, o eso creo.
He encontrado este codigo en esta pagina     https://www.dropboxforum.com/t5/Discuss-Developer-API/How-can-i-upload-file-to-my-Dropbox-account-with-vba/m-p/306546" rel="nofollow - https://www.dropboxforum.com/t5/Discuss-Developer-API/How-can-i-upload-file-to-my-Dropbox-account-with-vba/m-p/306546

Llamo a la funcio asi
Dim varArchivo As String
varArchivo = "Z:\Copia\Acces copia seguridad nube\Koala.jpg"
DB_PutFile varArchivo

Public Sub DB_PutFile(FileName As String)

Dim varToken As String
varToken = "EL TOKEN PROPORCIONADO POR DROPBOX en su aplicacion"


Dim req As MSXML2.ServerXMLHTTP60
Dim strFile As String
Dim Pos1 As Integer
Dim Pos2 As Integer
Set req = New MSXML2.ServerXMLHTTP60
Dim arg As String
strFile = ReadBinary(FileName)
arg = "{""path"":""/" & FileName & """,""mode"":{"".tag"":""overwrite""},""autorename"":false,""mute"":true}"
req.Open "POST", "https://content.dropboxapi.com/2/files/upload", False
req.setRequestHeader "Authorization", varToken     'Hay que poner el token de la aplicacion de dropbox en la variable
req.setRequestHeader "Content-Type", "application/octet-stream"
req.setRequestHeader "Content-length", Len(Result)
req.setRequestHeader "Dropbox-API-Arg", arg
req.setRequestHeader "User-Agent", "api-explorer-client"
req.send strFile

If req.Status = 200 Then
MsgBox req.responseText
Else
MsgBox req.Status & ": " & req.statusText
End If

End Sub

Al principio me daba un error, que parecia de referencias, al final he dado con la que es,  Microsoft XML, v6.0  en access 2013.

El error que me suelta ahora es no se a definido sub o function en la linea en rojo ReadBinary, no tengo claro que es ReadBinary???............He quitado el ReadBinary poniendolo asi  strFile = FileName y ahora me suelta un error ya como de conexion con dropbox

Standard API errors

CodeDescription
400Bad input parameter. Error message should indicate which one and why.
Aqui mas info sobre la API
https://www.dropbox.com/developers-v1/core/docs" rel="nofollow - https://www.dropbox.com/developers-v1/core/docs
https://www.dropbox.com/developers-v1/core/docs#files_put" rel="nofollow - https://www.dropbox.com/developers-v1/core/docs#files_put
https://www.dropbox.com/developers/documentation/http/documentation#files-upload" rel="nofollow - https://www.dropbox.com/developers/documentation/http/documentation#files-upload


Edito:
Ahora veo que puede ser ReadBinary, una funcion que no se cual es para asar el  directorio del archivo a Binario?????

La funcion no esta en la pagina web de donde he sacado el codigo







Publicado por: pitxiku
Fecha de publicación: 07/Mayo/2019 a las 18:27
ReadBinary puede ser una función personalizada para leer el archivo en binario. Puedes probar con la instrucción Open o con el objeto Stream de ADO:

- https://stackoverflow.com/questions/660312/how-can-i-read-a-binary-file-using-vba
- https://docs.microsoft.com/es-es/office/vba/language/reference/user-interface-help/open-statement
- https://www.w3schools.com/asp/ado_ref_stream.asp

Por otro lado, una duda: si estás en un dominio, ¿el departamento de IT no hace copias de seguridad del servidor?


Publicado por: rokoko
Fecha de publicación: 07/Mayo/2019 a las 18:42
Publicado originalmente por pitxiku pitxiku escribió:

Por otro lado, una duda: si estás en un dominio, ¿el departamento de IT no hace copias de seguridad del servidor?

Si, si que hacen. Pero suele ser un horror de gestion para que te den el archivo. Mi idea era ir haciendo copias poniendo la fecha en el nombre del archivo para tener una serie de copias. Yo me imagino que los de IT iran pisando la copia que se haga..... y por otro lado tengo ganas de hacerlo funcionar para alguna otra aplicacion y curiosidad...

He encontrado este codigo que creo que lo pasa a binaryo, es correcto???

Function FileReadBinary(sFileName As String) As Variant
    Dim iFileNum As Integer, lFileLen As Long
    Dim vThisBlock As Variant, lThisBlock As Long, vFileData As Variant
    
    On Error GoTo ErrFailed
    
    If Len(Dir$(sFileName)) > 0 And Len(sFileName) > 0 Then
        iFileNum = FreeFile
        Open sFileName For Binary Access Read As #iFileNum
        
        lFileLen = LOF(iFileNum)
        
        Do
            lThisBlock = lThisBlock + 1
            Get #iFileNum, , vThisBlock
            If IsEmpty(vThisBlock) = False Then
                If lThisBlock = 1 Then
                    ReDim vFileData(1 To 1)
                Else
                    ReDim Preserve vFileData(1 To lThisBlock)
                End If
                vFileData(lThisBlock) = vThisBlock
            End If
        Loop While EOF(iFileNum) = False
        Close iFileNum
        
        FileReadBinary = vFileData
    End If

    Exit Function
    
ErrFailed:
    Close iFileNum
    Debug.Print Err.Description



Lo he probado(sin saber que lo hace bien) y ahora solo me suelta el error 400 de dropbox........



Publicado por: pitxiku
Fecha de publicación: 07/Mayo/2019 a las 18:52
Revisa la cadena de argumentos, a ver si tienes algo raro. Por ejemplo, yo veo:

""path"":""/" & FileName & """: Estás usando la ruta y nombre del archivo en tu disco local, pero en la ayuda del API indican que ahí debe ir la ruta y nombre en Dropbox. Además, ellos usan la barra normal (/) para separar las carpetas, y en Windows se usa la invertida (\).

""mode"": No indicas un valor para este parámetro, aunque en la ayuda indican que hay un valor por defecto. Tal vez no sea necesario indicarlo, pero por si acaso...

{"".tag"":""overwrite""}: encierras este parámetro entre llaves, y todo el conjunto entre otras llaves. En la ayuda del API sólo está la llave "principal".


Publicado por: rokoko
Fecha de publicación: 07/Mayo/2019 a las 19:58
Tiene su miga esto, no hay formaCry. Me sigue soltando el error 400 de dropbox. He probado todo lo que me as dicho. Lo que si es claro que tenia mal era path, estaba utilizando el del disco local.
Ahora de momento lo tengo asi

para llamarla si
Dim varArchivo As String
varArchivo = "Z:\Acces copia seguridad nube\Koala.jpg"
DB_PutFile varArchivo


Public Sub DB_PutFile(FileName As String)

Dim varToken As String
varToken = "xxxxxxxxxxxxxxxxxxxxxxxxxx"

Dim varDirectorioDropbox As String
varDirectorioDropbox = "Aplicaciones/CopiaAccess/Koala.jpg"



Dim req As MSXML2.ServerXMLHTTP60
Dim strFile As String
Dim Pos1 As Integer
Dim Pos2 As Integer
Set req = New MSXML2.ServerXMLHTTP60
Dim arg As String
strFile = FileReadBinary(FileName)
'MsgBox strFile
arg = "{""path"":""/" & varDirectorioDropbox & """,""mode"":add,{"".tag"":""overwrite""},""autorename"":false,""mute"":true}"
req.Open "POST", "https://content.dropboxapi.com/2/files/upload", False
req.setRequestHeader "Authorization", varToken     'Hay que poner el token de la aplicacion de dropbox en la variable
req.setRequestHeader "Content-Type", "application/octet-stream"
req.setRequestHeader "Content-length", Len(Result)
req.setRequestHeader "Dropbox-API-Arg", arg
req.setRequestHeader "User-Agent", "api-explorer-client"
req.send strFile

If req.Status = 200 Then

'Debug.Print req.responseText
MsgBox req.responseText
Else
MsgBox req.Status & ": " & req.statusText
'Debug.Print req.responseText
'MsgBox req.responseText
End If


Publicado por: guarracuco
Fecha de publicación: 07/Mayo/2019 a las 21:57
Tienes un detalle que corregir en una de las lineas del Header:
req.setRequestHeader "Authorization", "Bearer " &  varToken 

Aunque la respuesta 400 no es la adecuada para este error, debes corregir este primero.
Estas a 2 toques de lograrlo.


-------------
https://tucondominioaldia.net


Publicado por: rokoko
Fecha de publicación: 07/Mayo/2019 a las 22:23
Asi esta con la correccion de guarruco, pero efectivamente sigue el error 400 bad request

A que puede deberse ese error????

Public Sub DB_PutFile(FileName As String)

Dim varToken As String
varToken = "xxxxxxxxxxxxxxxxxxxxxx"

Dim varDirectorioDropbox As String
varDirectorioDropbox = "Aplicaciones/CopiaAccess/Koala.jpg"



Dim req As MSXML2.ServerXMLHTTP60
Dim strFile As String
Dim Pos1 As Integer
Dim Pos2 As Integer
Set req = New MSXML2.ServerXMLHTTP60
Dim arg As String
strFile = FileReadBinary(FileName)
'strFile = FileName
MsgBox strFile
arg = "{""path"":""/" & varDirectorioDropbox & """,""mode"":add,{"".tag"":""overwrite""},""autorename"":false,""mute"":true}"
req.Open "POST", "https://content.dropboxapi.com/2/files/upload", False
req.setRequestHeader "Authorization", "Bearer " & varToken       'Hay que poner el token de la aplicacion de dropbox en la variable
req.setRequestHeader "Content-Type", "application/octet-stream"
req.setRequestHeader "Content-length", Len(Result)
req.setRequestHeader "Dropbox-API-Arg", arg
req.setRequestHeader "User-Agent", "api-explorer-client"
req.send strFile

If req.Status = 200 Then
MsgBox req.responseText
Else
MsgBox req.Status & ": " & req.statusText
End If
End Sub


Publicado por: guarracuco
Fecha de publicación: 07/Mayo/2019 a las 22:29
Busca en el panel de control de Dropbox credenciales de prueba (Sandbox Credentials) y me las envias por privado.
Ignoro si esa API tiene credenciales de prueba.

Imprime la respuesta del servidor y publicalo para ver el mensaje que devuelve la API.


-------------
https://tucondominioaldia.net


Publicado por: rokoko
Fecha de publicación: 07/Mayo/2019 a las 22:51
Publicado originalmente por guarracuco guarracuco escribió:

Busca en el panel de control de Dropbox credenciales de prueba (Sandbox Credentials) y me las envias por privado.
Ignoro si esa API tiene credenciales de prueba.

Imprime la respuesta del servidor y publicalo para ver el mensaje que devuelve la API.

A ver, lo de las credenciales de prueba no lo veo por ningun lado(uso version gratuita de dropbox) no se si sera por esto....
y en la ventana inmediato me sale esto

La variable utiliza un tipo de Automatización no admitido en Visual Basic
Error in call to API function "files/upload": HTTP header "Dropbox-API-Arg": could not decode input as JSON

Muchas gracias


Publicado por: guarracuco
Fecha de publicación: 07/Mayo/2019 a las 23:55
Option Compare Database
Dim access_token As String
Dim req As Object
Dim vardir As String
Dim varfile As String


Private Sub Command0_Click()
    Dim arg As String
    result = FRB(vardir)
    varfile = "\/TU_DIRECTORIO_EN_DRPBOX\/NOMBRE_Y_EXTENSION_FINAL_DEL_ARCHIVO_EN_DROPBOX"
    arg = "{""path"":""" & varfile & """,""mode"":""add"",""autorename"":false,""mute"":true}"
    Set req = CreateObject("WINHTTP.WinHTTPRequest.5.1")
    
    req.Open "POST", "https://content.dropboxapi.com/2/files/upload", False
    req.setRequestHeader "Authorization", "Bearer " & access_token       'Hay que poner el token de la aplicacion de dropbox en la variable
    req.setRequestHeader "Content-Type", "application/octet-stream"

    req.setRequestHeader "Dropbox-API-Arg", arg
    req.setRequestHeader "User-Agent", "api-explorer-client"
    req.send (result)
    
    If req.status = 200 Then
        Debug.Print req.responseText
    Else
        Debug.Print req.responseText
    End If
End Sub

Private Sub Form_Load()
access_token = "TU-TOKEN"

'ruta del archivo a enviar. Debes enmascarar las barras inclinadas para que sea formato JSON valido
vardir = "C:\\Users\\Carlos\\Documents\\MisOcx\\alter.txt"
End Sub

Function FRB(ByVal sRuta As String) As Byte()
    Dim b() As Byte
    Open sRuta For Binary As #1
    ReDim b(FileLen(sRuta) - 1) '''''****ESTE -1 ES LA SOLUCIÓN PARA QUE NO CORROMPA LOS ARCHIVOS******RESTARLE UN BYTE
    Get #1, , b
    Close #1
    FRB = b
End Function

Reemplaza tu token, nombre de carpeta remota y ruta del archivo a subir.



-------------
https://tucondominioaldia.net


Publicado por: rokoko
Fecha de publicación: 08/Mayo/2019 a las 00:26
Publicado originalmente por guarracuco guarracuco escribió:

Option Compare Database
Dim access_token As String
Dim req As Object
Dim vardir As String
.............

ClapClapClapClapClapClapClap funciona!!!
Madre mia, que arte teneis algunos en este mundillo.
Yo creo que ni metiendo todas las horas del mundo lo hago funcionar...complicado esto de las apis......

Mañana lo miro mas despacio y pregunto alguna duda..

Muchas muchas gracias

Saludos




Publicado por: guarracuco
Fecha de publicación: 08/Mayo/2019 a las 00:42
Un placer. Hay que realizar un ajuste en la ruta/nombre remoto, de lo contrario, crea dentro del directorio, uno nuevo.

varfile = "\/NOMBRE_Y_EXTENSION_FINAL_DEL_ARCHIVO_EN_DROPBOX"
La diferencia es remover el nomre del directorio, ya que el token esta asociado al mismo.
Recuerda enmascarar las barras inclinadas.

y para sobreescribir:
arg = "{""path"":""" & varfile & """,""mode"":""overwrite"",""autorename"":false,""mute"":true}"

Ayudando se aprende. Esta API es nueva para mi. Todas son muy parecidas.


-------------
https://tucondominioaldia.net


Publicado por: rokoko
Fecha de publicación: 08/Mayo/2019 a las 16:58
Hola

Alguna duda me queda..
Este parametro que es, algun tiempo de respuesta??   If req.status = 200 Then

Y por otro lado y probando pensando que no funcionaria, he creado un cuadro de dialogo para selecionar un archivo a subir y logicamente la ruta que crea es con una sola barra y no la doble barra para JSON, pero el archivo sube bien!!!
Funciona con barra simple y doble(JSON).




Publicado por: emiliove
Fecha de publicación: 08/Mayo/2019 a las 17:14
Hola Rokoko

El 200 es que la petición que estas haciendo fue correcta, y te va a devolver la respuesta.

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms767625%28v%3Dvs.85%29" rel="nofollow - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms767625(v%3Dvs.85)

Saludos.


Publicado por: rokoko
Fecha de publicación: 08/Mayo/2019 a las 21:19
Hola

Probando con algunos archivos de uno 25mb me a dado el error en esta linea  req.send (result)
-Se supero el tiempo de espera para esta operacion  error -21470122894(80072ee2)

Se puede solucionar esto, modificar el limite de tiempo o alguna otra solucion??

Saludos


Publicado por: pitxiku
Fecha de publicación: 09/Mayo/2019 a las 19:27
Puede que en vez de usar el método upload, tengas que usar una sesión para subir archivos grandes:

- https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start


Publicado por: rokoko
Fecha de publicación: 09/Mayo/2019 a las 20:05
Publicado originalmente por pitxiku pitxiku escribió:

Puede que en vez de usar el método upload, tengas que usar una sesión para subir archivos grandes:

- https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start


Justo ahora estaba probando y he conseguido subir un archivo de 144mbm en principio mas que suficiente para lo que quiero. He puesto esta linea.

Set req = CreateObject("WINHTTP.WinHTTPRequest.5.1")
req.SetTimeouts 30000, 1000000, 1000000, 1000000
req.Open "POST", "https://content.dropboxapi.com/2/files/upload", False
ResolveTimeout,ConnectTimeout,SendTimeout,ReceiveTimeout

Son tiempos en milisegundos, lo que no he encontrado es que limites se pueden poner.. Y esa linea tiene que ir antes de Open



Publicado por: pitxiku
Fecha de publicación: 09/Mayo/2019 a las 22:43
Entiendo que los tiempos que has puesto son más que suficientes (son casi 3 horas).

Menos el tiempo del envío del archivo(send), para los demás con un par de segundos debe sobrar.

Si el archivo no pasa de 150 mb no pasa nada. Pero si pasa, entiendo que sí debes usar una sesión.


Publicado por: guarracuco
Fecha de publicación: 10/Mayo/2019 a las 01:24
Quizas sea suficiente el cambiar el parametro false por true.
Esto indica que la solicitud se haga en modo asincrono de manera que no se detiene la ejecucion de codigo vba. Podrias colocar un reloj indicando que el proceso se esta ejecutando.
Hay un evento que te indica que el proceso finalizo. Utilizalo para detener el reloj.


-------------
https://tucondominioaldia.net


Publicado por: rokoko
Fecha de publicación: 10/Mayo/2019 a las 08:13
Publicado originalmente por guarracuco guarracuco escribió:

Quizas sea suficiente el cambiar el parametro false por true.
Esto indica que la solicitud se haga en modo asincrono de manera que no se detiene la ejecucion de codigo vba. Podrias colocar un reloj indicando que el proceso se esta ejecutando.
Hay un evento que te indica que el proceso finalizo. Utilizalo para detener el reloj.


He cambiado el parametro false a true en esta linea  req.Open "POST", "https://content.dropboxapi.com/2/files/upload", True   pero me suelta el error  "El dato necesario para completar esta operacion no esta disponible ahora"


Publicado originalmente por pitxiku pitxiku escribió:

Entiendo que los tiempos que has puesto son más que suficientes (son casi 3 horas).

Menos el tiempo del envío del archivo(send), para los demás con un par de segundos debe sobrar.

Si el archivo no pasa de 150 mb no pasa nada. Pero si pasa, entiendo que sí debes usar una sesión.

Pues si no pongo en todos parametro (3 ultimos) un tiempo generoso  me dice que se ha agotado el tiempo.


Mañana lo probare ya en realidad en el trabajo, y ya os contare. Deberia de ir bien, ademas los archivos a subir no son muy grandes, mas bien pequeños

Saludos


Publicado por: guarracuco
Fecha de publicación: 10/Mayo/2019 a las 14:36
CUando se utiliza en modo asincrono, hay que agregar luego de la linea send:
obj.waitForResponse


-------------
https://tucondominioaldia.net


Publicado por: rokoko
Fecha de publicación: 12/Mayo/2019 a las 10:32
Hola

Lo he probado en el trabajo en 3 bases de datos y funciona perfectamente, la verdad que es una gozada hacer copias de seguridad asi. O para subir a Dropbox lo que quieras.
Con este codigo estas limitado en teoria a 150 mb, pero modificandolo se podria subir archivos mas grandes.

Como resumen

https://www.dropbox.com/developers-v1/core/docs

https://www.dropbox.com/developers

https://dropbox.github.io/dropbox-api-v2-explorer/#files_upload

https://www.dropbox.com/developers/documentation/http/documentation

http://www.jose.it-berater.org/winhttp/settimeouts_method.htm

Y un ejemplo con varias opciones
https://www.dropbox.com/s/dda5vkcbw2hal2m/ArchivosNube.rar?dl=0

Son 3 parametros los que hay que pasar, el token de dropbox, la ruta dropbox con archivo y extension, y ruta del archivo a subir con archivo y extension.


Se puede cerra, muchas gracias a todos.



Publicado por: rokoko
Fecha de publicación: 18/Mayo/2019 a las 17:47
Cerrar el hilo por favor

Saludos



Imprimir página | Cerrar ventana