Upload single file to Google Drive in Golang

Setting Up Google Drive API for a Desktop Application

Step 1: Open Google Cloud Console

  1. Go to the Google Cloud Console.

Step 2: Create a New Project

  1. Click on the project dropdown menu at the top of the page.
  2. Click on New Project.
  3. Enter a name for your project and click Create.

Step 3: Select Your Project

  1. Select the project you just created from the project dropdown menu.

Step 4: Enable Google Drive API

  1. Navigate to API & Services -> Enabled APIs & Services.
  2. Click on + ENABLE APIS AND SERVICES at the top.
  3. Search for “Google Drive API” and click on it.
  4. Click Enable to enable the Google Drive API for your project.

Step 5: Create OAuth 2.0 Credentials

  1. Go to the Credentials page under API & Services.
  2. Click on CREATE CREDENTIALS at the top.
  3. Select OAuth client ID.
  4. Configure the consent screen if prompted:
    • Fill out the required fields and save.
  5. Under Application type, select Desktop app.
  6. Enter a name for your OAuth client (e.g., “Desktop App Client”).
  7. Click Create.

Step 6: Download Your Credentials

  1. After creating the OAuth client ID, you will see a dialog with your client ID and client secret.
  2. Click OK.
  3. Download the JSON file containing your credentials.

Google Drive API Integration for a Desktop Application in Go

Step-by-Step Code

Import

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/gin-gonic/gin"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/drive/v3"
	"google.golang.org/api/option"
)
  1. Retrieve a Token, Save the Token, and Return the Generated Client
getClient(config *oauth2.Config) *http.Client {
    tokFile := "token.json"
    tok, err := tokenFromFile(tokFile)
    if err != nil {
        tok = getTokenFromWeb(config)
        saveToken(tokFile, tok)
    }
    return config.Client(context.Background(), tok)
}
  1. Request a Token from the Web
getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
    authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
    fmt.Printf("Go to the following link in your browser then type the authorization code: \n%v\n", authURL)

    fmt.Print("Enter the authorization code: ")
    reader := bufio.NewReader(os.Stdin)
    authCode, err := reader.ReadString('\n')
    if err != nil {
        log.Fatalf("Unable to read authorization code: %v", err)
    }
    authCode = strings.TrimSpace(authCode)

    tok, err := config.Exchange(context.TODO(), authCode)
    if err != nil {
        log.Fatalf("Unable to retrieve token from web: %v", err)
    }
    return tok
}
  1. Retrieve a Token from a Local File
tokenFromFile(file string) (*oauth2.Token, error) {
    f, err := os.Open(file)
    if err != nil {
        return nil, err
    }
    defer f.Close()
    tok := &oauth2.Token{}
    err = json.NewDecoder(f).Decode(tok)
    return tok, err
}
  1. Save a Token to a File Path
saveToken(path string, token *oauth2.Token) {
    fmt.Printf("Saving credential file to: %s\n", path)
    f, err := os.Create(path)
    if err != nil {
        log.Fatalf("Unable to create file: %v", err)
    }
    defer f.Close()
    json.NewEncoder(f).Encode(token)
}
  1. Create or Get Folder in Google Drive
getOrCreateFolder(srv *drive.Service, folderName string) (string, error) {
    // Check if folder exists
    query := fmt.Sprintf("name='%s' and mimeType='application/vnd.google-apps.folder' and trashed=false", folderName)
    r, err := srv.Files.List().Q(query).Spaces("drive").Fields("files(id, name)").Do()

    if err != nil {
        return "", fmt.Errorf("unable to query files: %v", err)
    }

    if len(r.Files) > 0 {
        // Folder exists, return the ID    
        return r.Files[0].Id, nil
    }
    
    // Folder does not exist, create it
    folder := &drive.File{
        Name:     folderName,
        MimeType: "application/vnd.google-apps.folder",
    }
    folderFile, err := srv.Files.Create(folder).Do()
    
    if err != nil {
        return "", fmt.Errorf("unable to create folder: %v", err)
    }
    return folderFile.Id, nil
}

Main Function Implementation

  1. Upload a Single File to a Local Folder
fileData, _ := ctx.FormFile("file")

// Define the destination path
uploadDir := "assets"
dst := filepath.Join(uploadDir, fileData.Filename)

ctx.SaveUploadedFile(fileData, dst)
  1. Read Credentials File
b, err := os.ReadFile("./credentials.json") // This is the file we downloaded
if err != nil {
    log.Fatalf("Unable to read client secret file: %v", err)
}
  1. Parse Credentials and Get Client
config, err := google.ConfigFromJSON(b, drive.DriveFileScope)
if err != nil {
    log.Fatalf("Unable to parse client secret file to config: %v", err)
}
client := getClient(config)
  1. Create a New Google Drive Service
srv, err := drive.NewService(context.Background(), option.WithHTTPClient(client))
if err != nil {
    log.Fatalf("Unable to retrieve Drive client: %v", err)
}
  1. Example Usage of the Drive API
file, err := os.Open(dst)
if err != nil {
    log.Fatalf("Unable to open file: %v", err)
}
defer file.Close()

// Create folder if it does not exist
folderName := "GoLang test"
folderID, err := getOrCreateFolder(srv, folderName)
if err != nil {
    log.Fatalf("Unable to get or create folder: %v", err)
}
fmt.Printf("Folder ID: %s\n", folderID)

// Specify the folder ID here
f := &drive.File{
    Name:    fileData.Filename,
    Parents: []string{folderID},
}
driveFile, err := srv.Files.Create(f).Media(file).Do()
if err != nil {
    log.Fatalf("Unable to create file: %v", err)
}
fmt.Printf("File ID: %s\n", driveFile.Id)
err = file.Close()
if err != nil {
    log.Fatalf("Unable to close file: %v", err)
}
  1. Delete File from Local Folder
if driveFile.Id != "" {
    fmt.Println("Inside delete file")
    err := os.Remove(dst)
    fmt.Println("File delete err :: ", err)
}

You may also like

1 Comment

Leave a Reply