19

I decided to migrate from Google Drive API v2 to v3 and it was not an easy task. Even thought Google wrote this documentation, there are many gaps in it and there is not much information about this on the web.

I'm sharing here what I have found.

IvanRF
  • 7,115
  • 5
  • 47
  • 71

2 Answers2

45

First, read the official docs: v2 to v3 reference | Drive API v3 versus v2 | Migrate to v3


Download

Download has changed. The field downloadUrl does not exist anymore. Now, it can be achieved with this:

service.files().get(fileId).executeMediaAndDownloadTo(outputStream);

I tried the new field webContentLink but it returns HTML content, instead of the file's content. In other words, it gives you the link to the Drive web UI.


Upload

Upload only requires to change the word insert for create, nothing more.


Trash / Update

I wasted some time with this one . Used to be a simple service.files().trash(fileId).execute(). Docs say

files.trash -> files.update with {'trashed':true}

The example code for update on v2 makes a get on the file, sets new values and then calls update.

On v3, using update like that throws this exception:

{
  "code" : 403,
  "errors" : [ {
    "domain" : "global",
    "message" : "The resource body includes fields which are not directly writable.",
    "reason" : "fieldNotWritable"
  } ],
  "message" : "The resource body includes fields which are not directly writable."
}

The solution is to create an empty File setting only the new values:

File newContent = new File();
newContent.setTrashed(true);
service.files().update(fileId, newContent).execute();

Note: File refers to com.google.api.services.drive.model.File (it is not java.io.File).


List

Files returned by service.files().list() does not contain information now, i.e. every field is null. If you want list on v3 to behave like in v2, call it like this:

service.files().list().setFields("nextPageToken, files");

Docs on Search for files and folders use setFields("nextPageToken, files(id, name)") but there is no documentation on how to get all the info for a file. Now you know, just include "files".


Fields

Full resources are no longer returned by default. Use the fields query parameter to request specific fields to be returned. If left unspecified only a subset of commonly used fields are returned.

That last part is not totally true, since you are forced to use setFields in some cases. For example, if you use service.about().get().execute() you will get this error:

"The 'fields' parameter is required for this method."

which is solved by calling service.about().get().setFields("user, storageQuota").execute(), for instance.

At the end of the docs is mentioned as:

The fields query parameter should be specified for methods which return


For the rest of the changes, just follow the Google table on the docs.

IvanRF
  • 7,115
  • 5
  • 47
  • 71
  • 1
    Re: fields, retrieving *all* fields is discouraged as several fields are significantly more expensive than others. When at all possible, specify only the individual fields required by the app. If you really need all of them, that's fine. – Steve Bazyl Feb 02 '16 at 22:27
  • 1
    @SteveBazyl Indeed, using `fields` allows to optimize resources on both ends. Nevertheless, there is not much info about how to define this new parameter. – IvanRF Feb 03 '16 at 15:41
  • @SteveBazyl Regarding Drive API, I posted an issue while ago ([link](https://code.google.com/a/google.com/p/apps-api-issues/issues/detail?id=4131&thanks=4131&ts=1446735406)). I have another, but is that the correct place to post them? there are not much Google replies there – IvanRF Feb 03 '16 at 15:46
  • I just commented on and closed the issue you linked to. It's technically possible to do at the protocol level, the issue is more with the default implementation in the java client. I suggest either filing a feature request with the java client or modifying the implementation to suit your needs. – Steve Bazyl Feb 03 '16 at 23:43
  • Thanks for sharing, @IvanRF. I've ran into this issue: http://stackoverflow.com/questions/35532402/google-drive-v3-google-api-client-2-0-batch-upload-is-failing. Do you have any idea what might be wrong? – temuri Feb 21 '16 at 04:44
  • I am getting 'The resource body includes fields which are not directly writable.' error while upload `create` in `v3` version. Any idea? – Ankur Raiyani Mar 17 '16 at 07:52
  • 2
    Re fields: "[There] is not much info about how to define this new parameter." In 2017, I made 2 videos on using the 'fields' parameter: a) when reading data from an API (http://developers.googleblog.com/2017/04/using-field-masks-with-google-apis-for.html), and b) when updating data via an API (http://developers.googleblog.com/2017/04/using-field-masks-with-update-requests.html) – wescpy Jan 10 '18 at 01:49
  • 1
    @wescpy nice summary of field masks, thanks for sharing! – IvanRF Jan 26 '18 at 15:32
  • Not returning the full representation makes sense, but it's also a definite gotcha, especially given the pickiness of the client with respect to making calls to update files. – Pathogen Jun 25 '18 at 20:53
2

I don't have the reputation to comment (sorry), but the provided line of code in the accepted answer, service.about().get().setFields("user, storageQuota").execute(), does not run, instead it throws an attribute error:

    about = service.about().get().setFields("user", "storageQuota").execute()
AttributeError: 'HttpRequest' object has no attribute 'setFields'

Instead, the line should read:

service.about().get(fields = "user, storageQuota").execute()
Meg
  • 21
  • 3