Google Drive API - update file metadata only - google-api

I am trying to rename google drive file resource. I guess that I just am missing something since all other actions like getting list of files, inserting files, moving files between directories are working.
Precondition: trying to rename file resource using this doc https://developers.google.com/drive/v2/reference/files/update with java (with only JDK stuff). Also, I do not use gdrive java sdk, apache http client or other libraries... Just clean JDK tools.
So what I do:
Here is the file metadata I am trying to send.
Modify title property in this metadata
Here is the code:
URLConnection urlConnection = new URL("https://www.googleapis.com/drive/v2/files/" + fileId).openConnection();
if (urlConnection instanceof HttpURLConnection) {
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
httpURLConnection.setRequestMethod("PUT");
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestProperty("Authorization", "Bearer " + accessToken);
DataOutputStream outputStream = new DataOutputStream(httpURLConnection.getOutputStream());
outputStream.writeBytes(FILE_RESOURCE_METADATA_WITH_CHANGED_TITLE_IN_JSON);
outputStream.flush();
outputStream.close();
}
After making an actual call to API I receive 200 status code and File resource in response body (as expected) but title remains the same. So I got no error no changed title.
Moreover, the google drive api ignores any change in the file resource. It just returns same file resource without any changes applied (tried with title, description, originalFileName, parents properties).
What I tried also so far:
Sending only the properties that should be changed, like
{"title":"some_new_name"}
Result is same.
Changing PUT to PATCH. Unfortunately, PATCH is not supported by HttpURLConnection but workarounds gave same results. Changes are ignored.
Used google api exlorer (which can be found on the right side of API reference page) - and... it works. Filled only fileId and title property in request body and it worked. File is renamed.
What I am missing ?

Found the solution...
Adding this request property fixed the problem.
httpURLConnection.setRequestProperty("Content-Type", "application/json")

Try the sample java code given in the documentation.
Since the code deals to update existing file's metadata and content.
From the code, you will find file.setTitle(newTitle) which I think the one what you want to implement.
import com.google.api.client.http.FileContent;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import java.io.IOException;
// ...
public class MyClass {
// ...
/**
* Update an existing file's metadata and content.
*
* #param service Drive API service instance.
* #param fileId ID of the file to update.
* #param newTitle New title for the file.
* #param newDescription New description for the file.
* #param newMimeType New MIME type for the file.
* #param newFilename Filename of the new content to upload.
* #param newRevision Whether or not to create a new revision for this
* file.
* #return Updated file metadata if successful, {#code null} otherwise.
*/
private static File updateFile(Drive service, String fileId, String newTitle,
String newDescription, String newMimeType, String newFilename, boolean newRevision) {
try {
// First retrieve the file from the API.
File file = service.files().get(fileId).execute();
// File's new metadata.
file.setTitle(newTitle);
file.setDescription(newDescription);
file.setMimeType(newMimeType);
// File's new content.
java.io.File fileContent = new java.io.File(newFilename);
FileContent mediaContent = new FileContent(newMimeType, fileContent);
// Send the request to the API.
File updatedFile = service.files().update(fileId, file, mediaContent).execute();
return updatedFile;
} catch (IOException e) {
System.out.println("An error occurred: " + e);
return null;
}
}
// ...
}
Hope this give you some points.

Related

Creation Date PDF Google Drive

I want to change the creation date on a Google Drive PDF file. So, how can I achieve this?
public static File SetLastModified(string fileID, DateTime lastModified)
{
File file = DriveService.Files.Get(fileID).Fetch();
file.ModifiedDate = lastModified.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss.fff'Z'");
try
{
FilesResource.UpdateRequest request = DriveService.Files.Update(file, fileID);
request.SetModifiedDate = true;
file = request.Fetch();
}
catch (Exception e)
{
throw;
}
return file;
}
It is not possible to change the creation date of a file using Files:update() method
If you will check the request body for Files:update() , you can only modify the parameters listed in the table provided in the document. createdTime property is not included in the list.
The one being modified in your sample code is the modifiedTime property which is included in the list of editable properties.
If you want to have a file with a specified createdTime, you need to create a new file using Files:create(). createdTime can be modified as part of the request body
Additional Reference:
Drive API Quickstart - Setup Drive API for different platforms
Drive API - How to create Files

Google Drive Api Pdf export from Google Doc generate empty response

I'm using the export Google Drive API to retrieve a Google Doc as Pdf: https://developers.google.com/drive/v3/reference/files/export
I'm having the following problem: for documents bigger than a certain size (I don't know exactly the threshold, but it happens even with relatively small files around 1,5 MB) the API return a 200 response code with a blank result (normally it should contains the pdf data as byte stream), as you can see in the following screenshot:
I can successfully export the file via GoogleDrive/GoogleDoc UI with the "File -> Download as.. -> Pdf" command, despite it takes a bit of time.
Here is the file used for test (1.180 KB exported from Google Doc), I shared it so you can access to try export:
https://docs.google.com/document/d/18Cz7kHfEiDLeTWHyyoOi6U4kFQDMeg0D-CCJzILMMCk/edit?usp=sharing
Here is the (Java) code I'm using to perform the operation:
#Override
public GoogleDriveDocumentContent downloadFileContentAsPDF(String executionGoogleUser, String fileId) {
GoogleDriveDocumentContent documentContent = new GoogleDriveDocumentContent();
String conversionMimeType = "application/pdf";
try {
getLogger().info("GDrive APIs - Downloading file content in PDF format ...");
InputStream gDriveFileData = getDriveService(executionGoogleUser).files()
.export(fileId, conversionMimeType)
.executeMediaAsInputStream();
getLogger().info("GDrive APIs - File content as PDF format downloaded.");
documentContent.setFileName(null);
documentContent.setMimeType(conversionMimeType);
documentContent.setData(gDriveFileData);
} catch (IOException e) {
throw new RuntimeException(e);
}
return documentContent;
}
Does anyone has the same issue and know how to solve it?
The goal is to generate a pdf from a Google Doc.
Thanks
I think you should try using media downloadeder you will have to alter it for Google drive rather than storage service.
{
// Create the service using the client credentials.
var storageService = new StorageService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "APP_NAME_HERE"
});
// Get the client request object for the bucket and desired object.
var getRequest = storageService.Objects.Get("BUCKET_HERE", "OBJECT_HERE");
using (var fileStream = new System.IO.FileStream(
"FILE_PATH_HERE",
System.IO.FileMode.Create,
System.IO.FileAccess.Write))
{
// Add a handler which will be notified on progress changes.
// It will notify on each chunk download and when the
// download is completed or failed.
getRequest.MediaDownloader.ProgressChanged += Download_ProgressChanged;
getRequest.Download(fileStream);
}
}
static void Download_ProgressChanged(IDownloadProgress progress)
{
Console.WriteLine(progress.Status + " " + progress.BytesDownloaded);
}
Code ripped from here

How to find URL of google spreadsheet using spreadsheet ID using google java client?

How to find URL of google spreadsheet using spreadsheet ID using google java client? I don't want to build a string. I want to make call to google REST API and find out.
Files: list with search parm using the mime type for a sheet
mimeType = 'application/vnd.google-apps.spreadsheet'
Code from the documentation.
/**
* Retrieve a list of File resources.
*
* #param service Drive API service instance.
* #return List of File resources.
*/
private static List<File> retrieveAllFiles(Drive service) throws IOException {
List<File> result = new ArrayList<File>();
Files.List request = service.files().list();
do {
try {
FileList files = request.execute();
result.addAll(files.getItems());
request.setPageToken(files.getNextPageToken());
} catch (IOException e) {
System.out.println("An error occurred: " + e);
request.setPageToken(null);
}
} while (request.getPageToken() != null &&
request.getPageToken().length() > 0);
return result;
}
response contains:
Remember unless the user has access to the files the link wont work for them
"selfLink": "https://www.googleapis.com/drive/v2/files/1-0ReBjBqKh_Q9r1BDsC_BB9JgkeLoFPkDIXFcXiqQZ",
"alternateLink": "https://docs.google.com/spreadsheets/d/1-0ReBjBqKh_Q9r1BDsC_BB9JgkeLoFPkDIXFcXiqQZ/edit?usp=drivesdk",
"embedLink": "https://docs.google.com/spreadsheets/d/1-0ReBjBqKh_Q9r1BDsC_BB9JgkeLoFPkDIXFcXiqQZ/htmlembed",

Dynamics CRM Attachment Data Import Using SDK

I am trying to import Attachments/Annotations to CRM Dynamics, I am doing this using the SDK.
I am not using the data import wizard.
I am not individually creating Annotation entities, instead I am using Data Import Feature programmatically.
I mostly leveraged the DataImport sample from the SDK sample code (SDK\SampleCode\CS\DataManagement\DataImport).
Import import = new Import()
{
ModeCode = new OptionSetValue((int)ImportModeCode.Create),
Name = "Data Import"
};
Guid importId = _serviceProxy.Create(import);
_serviceProxy.Create(
new ColumnMapping()
{
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process),
SourceEntityName = sourceEntityName,
SourceAttributeName = sourceAttributeName,
TargetEntityName = targetEntityName,
TargetAttributeName = targetAttributeName
});
I am getting an error "The reference to the attachment could not be found".
The documentation says the crm async service will find the physical file on disk and upload it, my question is where does the async service look for attachment files?
I tried to map documentbody field to the full path of the attachment on the desk, but that still didn't work.
The answer below was provided before the question edits clarifying the use of the import wizard instead of the SDK. The answer below is specific to using the SDK.
When you are attaching files to an Annotation (Note) record in CRM via the SDK, you do use the documentbody attribute (along with mimetype), but you have to first convert it base64.
Something like this:
var myFile = #"C:\Path\To\My\File.pdf";
// Do checks to make sure file exists...
// Convert to Base64.
var base64Data = Convert.ToBase64String(System.IO.File.ReadAllBytes(myFile));
var newNote = new Entity("annotation");
// Set subject, regarding object, etc.
// Add the data required for a file attachment.
newNote.Attributes.Add("documentbody", base64Data);
newNote.Attributes.Add("mimetype", "text/plain"); // This mime type seems to work for all file types.
orgService.Create(newNote);
I found the solution in an obscure blog post, I think the documentation is misleading or unclear, the way this whole thing works, makes having the files available on the server disk for the async to process, odd.
To follow the same principle, all contents should be sent like the csv file itself while being linked to the same import.
To solve this we need create individual special Internal ImportFile for each physical attachment, and link it to the import that has the attachments record details.
As you see below with linking the attachments ImportFile using the ImportId and then setting the two properties (ProcessCode and FileTypeCode), it all worked in the end.
Suffice to say using this method is much more efficient and quicker than individually creating Annotation records.
foreach (var line in File.ReadLines(csvFilesPath + "Attachment.csv").Skip(1))
{
var fileName = line.Split(',')[0].Replace("\"", null);
using (FileStream stream = File.OpenRead(attachmentsPath + fileName))
{
byte[] byteData = new byte[stream.Length];
stream.Read(byteData, 0, byteData.Length);
stream.Close();
string encodedAttachmentData = System.Convert.ToBase64String(byteData);
ImportFile importFileAttachment = new ImportFile()
{
Content = encodedAttachmentData,
Name = fileName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
UseSystemMap = true,
ImportId = new EntityReference(Import.EntityLogicalName, importId),
ProcessCode = new OptionSetValue((int)ImportFileProcessCode.Internal),
FileTypeCode = new OptionSetValue((int)ImportFileFileTypeCode.Attachment),
RecordsOwnerId = currentUserRef
};
_serviceProxy.Create(importFileAttachment);
}
idx++;
}

Rename a folder / Collection with Google Documents List Data API v3.0

I am trying to rename a collection, but I get the error But
com.google.gdata.util.InvalidEntryException: Invalid request URI
, this is the code that I have
DocsService client = new DocsService("test testApp v1");
URL feedUrl = new URL("https://docs.google.com/feeds/default/private/full/folder%3A"+IDFOLDER);
DocumentListEntry newEntry = new FolderEntry();
newEntry.setId(IDFOLDER);
newEntry.setTitle(new PlainTextConstruct(newName));
client.insert(feedUrl, newEntry);
This is the way to do that or what i have wrong ?
Renaming a collection (or a document entry) is similar to retrieving the entry from the API, changing the title and sending an update (PUT) request to the document entry's edit URL.
You can use this code snippet to accomplish that in Java:
static DocumentListEntry renameDocument(DocsService client, String resourceUrl,
String newTitle) throws MalformedURLException, IOException,
ServiceException {
DocumentListEntry entry = client.getEntry(
new URL(resourceUrl), DocumentListEntry.class);
entry.setTitle(new PlainTextConstruct(newTitle));
DocumentListEntry updatedEntry = client.update(
new URL(entry.getEditLink().getHref()), entry);
// Check that updatedEntry has the new title.
return updatedEntry;
}

Resources