2
votes

I'm using the code from here: https://developers.google.com/drive/api/v3/manage-downloads#downloading_a_file

The code snippet I'm using is the following and placed in the main method:

    String fileId = "some file ID";
    OutputStream outputStream = new ByteArrayOutputStream();
    driveService.files().get(fileId)
    .executeMediaAndDownloadTo(outputStream);

I have found no sign of the code actually downloading the file, nor do I know where the file is IF it actually downloads. I'm not sure if I am using the proper scope to gain permission to download files. I am able to upload, list, and delete files as long as I know the fileID, but downloading seems to not work.

    private static final List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE);

Alternatively, I'm trying to create a method to enact the download protocol like so:

    private static void downloadFile(Drive service, File file (or String fileID)){
    }

but am not sure on how to do so. I've tried looking for samples online but most are from v1 or v2 apis and don't seem to work for me.

Also, I've read somewhere that it is not possible to download a Folder. Instead, I have to download each item in the folder one by one. So do I have to make an Arraylist/list/array of the fileIDs and iterate through it after initializing a variable to represent fileID?

Edit: Some progress has been made, but I still have some problems I'm trying to thrash out.

    List<File> files = result.getFiles();
    File newFile;
    if (files == null || files.isEmpty()) {
        System.out.println("No files found.");
    } else {
        System.out.println("Files:");
        for (File file : files) {
            System.out.printf("%s (%s)\n", file.getName(), file.getId());
            String fileId = file.getId();
            //System.out.println(fileId);
            String fileName = file.getName();
            //System.out.println(fileName);
            OutputStream outputstream = new FileOutputStream();
            service.files().get(fileId)
            .executeMediaAndDownloadTo(outputstream);
            outputstream.flush();
            outputstream.close();
    }

What I want: The above code is in the main method. I don't know if this is the proper way to do it, but as the program fetches each file and executes the System.out.printf, I also want it to download that file (with the same mimeType, and pref the same name too) into the destination set in the OutputStream constructor (C://User//some name//Downloads).

What I've tried: From what I've tested, it only downloads the first file exactly the way I want, but only because I specify the name and extension in OutputStream. I've initialized variables 'fileId' and 'fileName' so that they will change according to the info as the program fetches the metadata for the next file, but I don't know how to change or set multiple constructors into this code:

    OutputStream outputstream = new FileOutputStream();
            service.files().get(fileId)
            .executeMediaAndDownloadTo(outputstream);

to download all the files.

My folder hierarchy in Google Drive is like this:

Logs

-- bin (folder)

---- bunch of .bin files

-- .xml file

-- .xml file

1

1 Answers

3
votes

You are using a ByteArrayOutputStream object as the output of your download. If your program terminates without having saved the contents of this object somewhere, you will not be able to find this information in your computer's disk, as it is not written to it but rather saved in memory as a buffered byte-array (refer to the previous link for more information).

If you want to save the output of the download to the file, I suggest you use instead a FileOutputStream as the destination of your download. In order to do that, you have to modify your code as follows:

  1. Add the appropriate import declaration:

    import java.io.FileOutputStream;
    
  2. Modify your outputStream variable assignment as follows:

    OutputStream outputStream = new FileOutputStream('/tmp/downloadedfile');
    

    Where the parameter passed to FileOutputStream should be the desired destination path of your download.

  3. After writing any contents to your file, add the following lines of code:
    outputStream.flush();
    outputStream.close();
    
    This will ensure that your file is being written to properly.

In regards to downloading a folder, you are completely right - you will first need to fetch the folder you want to download, and each of their children. In order to better understand how to do it, I suggest you check out the following answer: Download folder with Google Drive API

Edit - example downloading a folder

String destinationFolder = "/tmp/downloadedfiles/";
List<File> files = result.getFiles();
File newFile;
if (files == null || files.isEmpty()) {
  System.out.println("No files found.");
} else {
  System.out.println("Files:");
  for (File file : files) {
    System.out.printf("%s (%s)\n", file.getName(), file.getId());
    String fileId = file.getId();
    String fileName = file.getName();
    OutputStream outputstream = new FileOutputStream(destinationFolder + fileName);
    service.files().get(fileId)
           .executeMediaAndDownloadTo(outputstream);
    outputstream.flush();
    outputstream.close();
  }
}