Integrazione con Google Drive

Nelle ultime versioni di QualiWare, a partire dalla 2023.00.17, sono disponibili una serie di funzionalità per l’interfacciamento con Google Drive. Questo interfacciamento permette di importare una serie di documenti da Google Drive (disco o cartella condivisa) a QualiWare, e viceversa.

Importazione da Google Drive a QualiWare

Su QualiWare è disponibile un apposito form indipendente che permette di importare documenti da un servizio in cloud (tra cui Google Drive). Si rimanda all’apposita pagina della guida per approfondirne il funzionamento.

È bene specificare, comunque, che è possibile utilizzare le funzioni elencate nell’apposito paragrafo di questa pagina per modificare ulteriormente il form ed aggiungerci determinate funzionalità.

Esportazione da QualiWare a Google Drive

Per esportare un gruppo di documenti da QualiWare a Google Drive è necessario, da parte dell’amministratore del Drive:

  1. creare un account di servizio, e fornire le credenziali all’amministratore di QualiWare
  2. condividere, con l’account di servizio, l’intero Drive, oppure le cartelle di destinazione dei documenti da esportare

Entrambi i passaggi saranno spiegati nel dettaglio nei seguenti paragrafi.

Creazione dell’account di servizio

L’account di servizio si può creare e configurare all’interno della Google Cloud Platform (CGP). Per farlo, bisogna accedere alla console e, da qui, procede alla sezione “IAM”. Per aggiungerne uno, bisogna, come indicato nell’immagine, accedere alla sezione “Service accounts” e poi cliccare su “Create Service account”.

 

 

I dati essenziali da specificare per l’account di servizio sono un nome ed un ID.

 

 

Dopo avere creato l’account, è necessario creare una chiave di accesso per permetterne l’utilizzo tramite API. Si può fare premere sull’icona nella colonna “Actions” e poi su scegliere “Manage keys”.

 

 

Dalla schermata delle chiavi, sarà poi sufficiente cliccare su “Add Key” e poi su “Create new key”. Si aprirà una schermata che consentirà di scegliere il modo in cui generare la chiave. La modalità più semplice è quella di utilizzare il formato JSON, naturalmente con le dovute precauzioni. Il contenuto del JSON generato sarà ciò che bisognerà fornire all’amministratore di QualiWare per poter impostare i servizi di esportazione. In particolare, il JSON è ciò che dovrà essere passato alla funzione GDriveGetService per effettuare l’autenticazione tra QualiWare e il Drive (per i dettagli, si veda il paragrafo apposito).

L’ultimo passaggio da effettuare, per completare la configurazione dell’utente di servizio, è abilitare l’utilizzo delle API di Google Drive da parte dell’account in questione. Per farlo, andare nella sezione “APIs and services” della console, scegliere “Enabled APIs and services”, poi “Enable APIs and services”. Fatto ciò, basta proseguire scegliendo di attivare quelle relative a Google Drive.

 

Funzioni

Di seguito l’elenco delle funzioni che permettono la gestione dei file su Google Drive. 

  • QWGoogle.DriveGetService(<Json>): restituisce l’oggetto servizio da passare nelle altre funzioni come parametro service. Nel parametro Json viene passato il contenuto del file JSON scaricato in fase di creazione della chiave dell’account di servizio.
  • QWGoogle.GDriveGetFolderIDByName(<service>,<folderName>,<parentFolderId>): restituisce l’ID di una cartella a partire dal nome. Il parametro parentFolderId contiene l’Id dell’eventuale cartella all’interno della quale è contenuta la cartella di cui è stato specificato il nome. Questo parametro va lasciato Nothing nel caso si desideri cercare la cartella in tutto lo spazio di archiviazione condiviso. Se la cartella non esiste, la funzione ritorna Nothing. ATTENZIONE: se non viene specificato il parametro parentFolderId, la funzione cerca in tutto lo spazio di archiviazione condiviso. Si tenga quindi in considerazione che:
    • è di fondamentale importanza che i nomi delle cartelle di primo livello siano univoci nello spazio di archiviazione stesso
    • la funzione può essere estremamente lenta (nell’ordine dei minuti) a ricavare l’ID della cartella, nel caso l’account Google utilizzato abbia un Drive corposo e/o dei Drive condivisi. Può quindi essere necessario specificare un parentFolderID per ottenere il risultato in una frazione di secondo, 
  • QWGoogle.GDriveGetFolderNameByID(<service>,<folderId>): recupera il nome della cartella a partire dall’ID passato nel parametro folderId. Se la cartella non esiste, la funzione ritorna Nothing.
  • QWGoogle.GDriveCreateFolder(<service>,<name>,<parentFolderId>,<errmsg>): crea una cartella con il nome specificato nel parametro name all’interno della cartella il cui ID è specificato nel parametro parentFolderId. Questa funzione ritorna l’ID della cartella se l’operazione è andata a buon fine, Nothing altrimenti, e, in questo caso, nel parametro errmsg è contenuta la descrizione dell’errore.
    NOTA: se la cartella esiste già, ne viene restituito l’ID.
  • QWGoogle.GDriveGetFiles(<service>,<folderId>,<optional recurse>,<optional filter>): restituisce un oggetto DBArray con informazioni relative ai file contenuti nella cartella il cui ID è specificato nel parametro folderID. Ogni elemento dell’array corrisponde ad un file, e consiste a sua volta in un DBArray di 5 elementi. Il primo è il nome del file con relativa estensione, il secondo l’ID, il terzo la data di ultima modifica, il quarto la dimensione in byte, e il quinto il path senza nome del file (e la cui radice è la cartella specificata nel primo tab del form). Il parametro opzionale recurse, se True, consente di recuperare i file anche dalle sotto cartelle. Il parametro opzionale filter consente di filtrare i file in base a parte del nome. E’ possibile anche usare il carattere * come wildcard.
  • QWGoogle.GDriveGetFolders(<service>,<folderId>): restituisce un oggetto DBArray con informazioni relative alle sottocartelle contenute nella cartella il cui ID è specificato nel parametro folderID. Gli elementi dell’array restituito sono a loro volta oggetti DBArray di due elementi. Il primo è il nome della sottocartella, il secondo il suo ID.
  • QWGoogle.GDriveDeleteFileOrFolder(<service>,<name>,<folderId>,<errmsg>)*: cancella il file o la sottocartella il cui nome è contenuto nel parametro name e che si trova nella cartella il cui ID è specificato nel parametro folderID. Questa funzione ritorna True se l’operazione è andata a buon fine, False altrimenti, e, in questo caso, nel parametro errmsg è contenuta la descrizione dell’errore. N.B. è possibile cancellare solo file caricati tramite script.
  • QWGoogle.GDriveDeleteFileOrFolderByID(<service>,<ID>,<errmsg>)*: cancella il file o la sottocartella il cui ID è contenuto nel parametro ID. Questa funzione ritorna True se l’operazione è andata a buon fine, False altrimenti, e, in questo caso, nel parametro errmsg è contenuta la descrizione dell’errore. N.B. è possibile cancellare solo file caricati tramite script.
  • QWGoogle.GDriveGetFile(<service>,<name>,<folderId>,<errmsg>): scarica il file il cui nome è contenuto nel parametro name e che si trova nella cartella il cui ID è specificato nel parametro folderID. Ritorna il percorso del file scaricato, oppure Nothing se l’operazione non è andata a buon fine e, in questo caso, nel parametro errmsg è contenuta la descrizione dell’errore.
  • QWGoogle.GDriveGetFileByID(<service>,<ID>,<errmsg>): scarica il file il cui ID è contenuto nel parametro ID. Ritorna il percorso del file scaricato, oppure Nothing se l’operazione non è andata a buon fine e, in questo caso, nel parametro errmsg è contenuta la descrizione dell’errore.
  • QWGoogle.GDriveUploadFile(<service>,<path>,<name>,<folderId>,<errmsg>): carica il file dal percorso specificato nel parametro path attribuendogli il nome contenuto nel parametro name e mettendolo nella cartella il cui ID è specificato nel parametro folderID. Questa funzione ritorna True se l’operazione è andata a buon fine, Falsealtrimenti, e, in questo caso, nel parametro errmsg è contenuta la descrizione dell’errore. Da notare che la data di ultima modifica del file viene assegnata su Google Drive uguale a quella del file caricato, il che consente di verificare eventuali aggiornamenti intervenuti in locale o su GDrive. Si noti che questa funzione non aggiunge automaticamente l’estensione al nome del file.
  • QWGoogle.GDriveRenameFileOrFolder(<service>,<oldname>,<newname>,<folderId>,<errmsg>): rinomina il file o la sottocartella il cui nome è contenuto nel parametro oldname e che si trova nella cartella il cui ID è specificato nel parametro folderID, assegnandogli il nome specificato nel parametro <newname> . Questa funzione ritorna True se l’operazione è andata a buon fine, False altrimenti, e, in questo caso, nel parametro errmsg è contenuta la descrizione dell’errore. 
  • QWGoogle.GDriveRenameFileOrFolderByID(<service>,<ID>,<newname>,<errmsg>): rinomina il file o la sottocartella il cui ID è contenuto nel parametro ID, assegnandogli il nome specificato nel parametro <newname>. Questa funzione ritorna True se l’operazione è andata a buon fine, False altrimenti, e, in questo caso, nel parametro errmsg è contenuta la descrizione dell’errore. 

* La cancellazione di un file è possibile solo se l’utente di servizio è proprietario (owner) del file stesso e, quindi, se l’ha creato lui. Diversamente, l’uso delle funzioni ritorna l’errore “forbidden”.

Esempio

Il codice riportato di seguito su Google Drive, in una cartella condivisa chiamata “ActiveDoc”, i file relativi ad una categoria documentale di QualiWare, mettendoli in una sottocartella il cui nome è uguale al nome della categoria, e attribuendo ai file un nome composto dal codice, dal titolo e dalla revisione. 

' Assegnare alla variabile "json" il contenuto del json scaricato in fase di creazione della chiave
Dim json As String = "{
                ""type"": ""sxxxxx"",
                ""project_id"": ""sxxxxx"",
                ""private_key_id"": ""sxxxxx"",
                ""private_key"": ""-----BEGIN PRIVATE KEY-----

-----END PRIVATE KEY-----\n"",
                ""client_email"": ""sxxxxx"",
                ""client_id"": ""sxxxxx"",
                ""auth_uri"": ""https://accounts.google.com/o/oauth2/auth"",
                ""token_uri"": ""https://oauth2.googleapis.com/token"",
                ""auth_provider_x509_cert_url"": ""https://www.googleapis.com/oauth2/v1/certs"",
                ""client_x509_cert_url"": ""https://www.googleapis.com/robot/v1/metadata/x509/xxxxxxxxx"",
                ""universe_domain"": ""googleapis.com""
                }"

'  Create Drive API service.
Dim Service As Google.Apis.Drive.v3.DriveService=QWGoogle.GDriveGetService(json)

Dim tipo as string="DM7TEST" ' codice della categoria da esportare
Dim cartella as string="ActiveDoc" ' Nome della sottocartella in cui esportare i documenti

dim q as new QWTable()
q.database=form.GetDataBase()
q.sql="select NOME from TIPI_DOC where TIPO=:TIPO"
q.params("TIPO")=tipo
q.requestlive=false
q.active=true

dim nome_categoria as string=q.rowset.fields(1).value

q.active=false

Dim i as integer
dim errmsg as string
dim ok as boolean
dim id as string=QWGoogle.GDriveGetFolderIDByName(service,cartella,nothing) ' Recupera l'ID della cartella principale in cui inserire i file
dim nome_cartella_categoria as string=Sane_Filename(nome_categoria)
dim id_categoria as string=QWGoogle.GDriveCreateFolder(service,nome_cartella_categoria,id,errmsg)
if not id is nothing
        q.sql="select TIPO,TIPO_CONT,NUMERO,IND_REV,TITOLO,_CODDOC from DOCUMENT where TIPO=:TIPO and PUBBLICATO=1"
        q.params("TIPO")=tipo
        q.requestlive=false
        q.active=true
        
        dim files as DBArray=QWGoogle.GDriveGetFiles(service,id_categoria)

        ok=true
        while not q.rowset.endofset and ok
                dim path as string=form.GetSession().GetDocumentPath(q.rowset.fields("_CODDOC").value)
                dim nomefile as string=q.rowset.fields("TIPO_CONT").value+"-"+q.rowset.fields("NUMERO").value+" "+Sane_FIlename(q.rowset.fields("TITOLO").value)+" rev. "+ltrim(str(q.rowset.fields("IND_REV").value))+System.IO.Path.GetExtension(path)

                ' Cerca nei file attuali se è presente
                dim upload as boolean=true

                for i=1 to files.size
                        if files(i)(1)=nomefile
                                dim dtqw as DateTime=files(i)(3)
                                dim dtG as DateTime=System.IO.File.GetLastWriteTime(path)
                                
                                if dtQW.Year=dtG.Year and dtQW.Month=dtG.Month and dtQW.Day=dtG.Day and dtQW.Hour=dtG.Hour and dtQW.Minute=dtG.Minute and dtQW.Second=dtG.Second
                                        upload=false
                                End If
                                files(i).add(true) ' per marcarlo come presente 
                                Exit for
                        End If
                next

                if upload
                        ok=QWGoogle.GDriveUploadFile(Service,path,nomefile,id_categoria,errmsg,q.rowset.fields("TITOLO").value)
                End If
                q.rowset.next()
        End while
        q.active=false

        if ok
        ' Cancella eventuali file in più presenti nella cartella di esportazione
                for i=1 to files.size
                        if files(i).Size=3
                                QWGoogle.GDriveDeleteFileOrFolder(service,files(i)(1),id_categoria,errmsg)
                        End If
                next     
        End If   
End If