0
votes

In my application, I am trying to force a download of a file from a Google Team Drive when the user clicks on a link on a form in my application.

A few updates:

  1. I have code that can upload to the Team Drive as well as create folders on the Team Drive.

  2. The "Team Drives support - This application works properly with files in Team Drives." on the Google Drive API settings CANNOT be enabled - I can check this box, but I cannot click the Save Changes button, since the button is always disabled. However, I don't think that is the issue, since I can interact with the Team Drive in my code.

I have read the Google documentation, which is very limited:

https://developers.google.com/drive/v3/web/manage-downloads

https://developers.google.com/drive/v3/reference/files/get

I have also read through a few posts:

Download files from google drive using java API

But, I can't find an answer that works. I have built some code which uses a Service Account. The code sets the drive service and uses the Service Account as the credentials. I based the download part of my code from this Google documentation example:

https://developers.google.com/drive/v3/web/manage-downloads#examples

Here is the code I am using:

public static void downloadFile(String fileID) {
    // Set the drive service...
    Drive service = null;
    try {
        service = getDriveService();
    } catch (IOException e) {
        e.printStackTrace();
    }
    OutputStream outputStream = new ByteArrayOutputStream();
    try {
        service.files().get(fileID).executeMediaAndDownloadTo(outputStream);
        // NEED CODE HERE???????


    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * Build and return an authorized Drive client service.
 * 
 * @return an authorized Drive client service
 * @throws IOException
 */
public static Drive getDriveService() throws IOException {
    Logger.info("GoogleDrive: getDriveService: Starting...");
    GoogleCredential credential = null;
    Drive googleDrive = null;
    try {
        credential = authorize();
        Logger.info("GoogleDrive: getDriveService: Credentials set...");
        googleDrive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME).build();
    } catch (IOException ex) {
        System.out.println(ex.toString());
        ex.printStackTrace();
    }
    return googleDrive;
}

/**
 * Creates an authorized Credential object.
 * 
 * @return an authorized Credential object.
 * @throws IOException
 */
@SuppressWarnings("deprecation")
public static GoogleCredential authorize() throws IOException {
    GoogleCredential credential = null;
    String credentialsFileName = "";
    try {
        Logger.info("GoogleDrive: authorize: Starting...");

        Logger.info("GoogleDrive: authorize: Getting credentialsFileName path...");
        credentialsFileName = Configuration.root().getString("google.drive.credentials.file");
        Logger.info("GoogleDrive: authorize: credentialsFileName = " + credentialsFileName);

        Logger.info("GoogleDrive: authorize: Setting InputStream...");
        InputStream in = GoogleDrive.class.getClassLoader().getResourceAsStream(credentialsFileName);
        if (in == null) {
            Logger.info("GoogleDrive: authorize: InputStream is null");
        }
        Logger.info("GoogleDrive: authorize: InputStream set...");

        Logger.info("GoogleDrive: authorize: Setting credential...");
        credential = GoogleCredential.fromStream(in, HTTP_TRANSPORT, JSON_FACTORY)
                .createScoped(Collections.singleton(DriveScopes.DRIVE));
    } catch (IOException ex) {
        System.out.println(ex.toString());
        System.out.println("Could not find file " + credentialsFileName);
        ex.printStackTrace();
    }
    Logger.info("GoogleDrive: authorize: Ending...");
    return credential;
}

When my code runs, there are no errors and nothing happens. I am guessing I am missing some code in the downloadFile function. If I am missing something or incorrect in my coding, please feel free to provide examples or the correct code I should be using.

I appreciate the help.

1

1 Answers

2
votes

This demo does not use service accounts.

I'm just going to demonstrate how I downloaded a Team drive file and hopefully it gives you insight on your project.

The foundation of the code was taken from Drive API Java Quickstart:

public static void main(String... args) throws IOException, GeneralSecurityException {
        // Build a new authorized API client service.
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
        Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
                .setApplicationName(APPLICATION_NAME)
                .build();

       //this is what you're looking for - a way to download a file using 'webContentLink'
        try {        
              Desktop desktop = java.awt.Desktop.getDesktop();
              //place your webContentLink in the oURL variable
              URI oURL = new URI("https://drive.google.com/a/google.com/uc?id=YOUR_FILE_ID&export=download");
              desktop.browse(oURL);

        } catch (Exception e) {
            e.printStackTrace();
        }
}

Upon execution, this program opens a blank browser window and downloads the file to your computer.

The way I generated the webContentLink was just use the Files.get Try-it and made sure I set supportsTeamDrives to true and also setting fields parameter to webContentLink so it returns just that.

Of course you can always use the Java files.get programmatically to fetch webContentLink but fetching the webContentLink using the Try-it was easier for testing purposes.