Google Drive API - Unable to export large file - google-drive-api

I am using google API to get content from gdoc file. I can't get content without exporting it. So, I am exporting into "application/vnd.openxmlformats-officedocument.wordprocessingml.document" mimetype to get content of file.
Here is the code to export the file:
$files = $service->files->export(
$fileId,
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
[
'alt' => 'media',
]
);
If Gdoc size is more than 10 mb and tries to export files via google API. It's throwing below error message.
{\"error\": {\"errors\": [ \"domain\": \"global\", \"reason\": \"exportSizeLimitExceeded\",\"message\": \"This file is too large to be exported.\" } ], \"code\": 403, "message\": \"This file is too large to be exported.\"}"}
I have used this library:
https://github.com/googleapis/google-api-php-client
As per the documentation, I can't export more than 10 mb.
Is there any way to export a file that contains more than 10MB size via Google API call?

Related

Chrome Extension - Read Local Text File

Hi I have a Chrome Extension and I would like for it to be able to read local text files.
I remember years ago, Chrome supports chrome.fileSystem. However, this has since been deprecated.
The closest thing I could get to reading any sort of file was this code below:
async function getFile(){
//Only able to read files in the extension folder.
//not allowed on local resources
var url = chrome.runtime.getURL('manifest.json');
var response = await fetch(url);
var data = await response.json();
console.log(data);
}
However, when I tried to fetch() from a url like C:\\Users\\user\\Desktop\\TestFolder\\test.txt, I would get the following error message:
Not allowed to load local resource
I have also added the "storage" permissions in my manifest.json correctly I believe.
"permissions" : [
"cookies", "tabs",
"webNavigation",
"storage",
"http://*/",
"https://*/"
]
Is there a newer version of chrome.fileSystem or any other way I could use to read a text file stored locally?
My Chrome Version is : 100.0.4896.75

Unable to update Google Drive files using Drive API v3 -- The resource body includes fields which are not directly writable

I am trying to use Google Drive API (v3) to make updates to documents
in Google Drive.
I have read this migration guide:
Google Drive API v3 Migration
And coded it to make a new empty File() with the details I want to update
and then calling execute() with that and the file ID.
But i am still getting an error. Can anyone point out where I am doing wrong?
thanks alot!!
Error:
{
"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."
}
Code snippet below:
File newFileDetails = new File();
FileList result = service2.files().list()
.setPageSize(10)
.setFields("nextPageToken, files(id, name)")
.execute();
List<File> files = result.getFiles();
if (files == null || files.size() == 0) {
System.out.println("No files found.");
} else {
System.out.println("Files:");
for (File file : files) {
if (file.getName().equals("first_sheet")) {
System.out.printf("%s (%s)\n", file.getName(), file.getId());
newFileDetails.setShared(true);
service2.files().update(file.getId(), newFileDetails).execute();
}
}
}
I had the same issue and found a solution. The key point is: you must create a new File object without Id and use it in update() method. Here is a piece of my code:
val oldMetadata = service!!.files().get(fileId.id).execute()
val newMetadata = File()
newMetadata.name = oldMetadata.name
newMetadata.parents = oldMetadata.parents
newMetadata.description = idHashPair.toDriveString()
val content = ByteArrayContent("application/octet-stream", fileContent)
val result = service!!.files().update(fileId.id, newMetadata, content).execute()
It works. I hope it'll help you.
Referring to https://developers.google.com/drive/v3/reference/files#resource-representations, you can see that shared isn't a writable field. If you think about it, this makes perfect sense. You can share a file by adding a new permission, and you can check if a file has been shared by reading the shared property. But saying a file is shared, other than by actually sharing it, makes no sense.
in the code it looks like this
Drive service... // your own declared implementation of service
File file = new File(); //using the com.google.api.services.drive.model package
// part where you set your data to file like:
file.setName("new name for file");
String fileID = "id of file, which you want to change";
service.files().update(fileID,file).execute();
trying to change the fields from remote files, and rewriting to this file can throw the security exception like exception below.
but it is not a solution for your question.
If you want to share file to another google account by email, you can do it with reimplementing authorization to authorization with using service account of your app, and the add the needed email, as owner of the file.
I was doing the same thing. My goal was to share my file programmatically with my Python code.
And yes, I was getting the same error:
"The resource body includes fields which are not directly writable"
I solved this problem by adding the service's email address of my Virtual Machine (I created it on my Compute Engine dashboard) to Editors of the file.
Then I ran this Python code in my VM:
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
# Took the json file from my Google Cloud Platform (GCP) → IAM & Admin → Service Accounts:
service_key_file = 'service_key.json'
scope = 'https://www.googleapis.com/auth/drive'
credentials = ServiceAccountCredentials.from_json_keyfile_name(service_key_file, scopes=scope)
driveV3 = build('drive', 'v3', credentials=credentials)
fileId = '1ZP1xZ0WaH8w2yaQTSx99gafNZWawQabcdVW5DSngavQ' # A spreadsheet file on my GDrive.
newGmailUser = 'testtest#gmail.com'
permNewBody = {
'role': 'reader',
'type': 'user',
'emailAddress': newGmailUser,
}
driveV3.permissions().create(fileId=fileId, body=permNewBody).execute()
print(f"""The file is now shared with this user:
{newGmailUser}\n
See the file here:
https://docs.google.com/spreadsheets/d/1ZP1xZ0WaH8w2yaQTSx99gafNZWawQabcdVW5DSngavQ""")

Translate the Source File into SVF format - Translation Failure

I've been following the Autodesk Model Derive API tutorial on
Extracting Data From a Source File and keep getting a Translation Failure when attempting to convert the uploaded source file to SVF.
I have tried .step, .sldprt, .stl and .igs files (supported file extensions here), but all seem to throw the same error message.
The request
def self.convert_to_svf(urn, key)
url = URI("https://developer.api.autodesk.com/modelderivative/v2/designdata/job")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
body = {"input": { "urn": "#{urn}", "compressedUrn": true, "rootFilename": "#{key}" }, "output": { "formats": [{ "type": "svf", "views": ["2d", "3d"] }] }}
request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["authorization"] = 'Bearer ' + token
request.body = body.to_json
JSON.parse(http.request(request).read_body)
end
The response
{"type"=>"manifest", "hasThumbnail"=>"false", "status"=>"failed", "progress"=>"complete", "region"=>"US", "urn"=>"dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6aXNvcXVlLzE4Ynk4cG9pbnQ1X2dvb2R5ZWFyLmlncw", "derivatives"=>[{"name"=>"LMV Bubble", "hasThumbnail"=>"false", "status"=>"failed", "progress"=>"complete", "messages"=>[{"type"=>"error", "message"=>"Translation failure", "code"=>"TranslationWorker-InternalFailure"}], "outputType"=>"svf"}]}
I did not see an obvious issue in your code snippet, however may I know if you have uploaded the source file(s) in zip format or only the single file of the original format (say .step, .sldprt, .stl and .igs) ?
I had the practice on the relevant APIs. I tested with Inventor assembly (with sub-assemblies and parts) and AutoCAD drawing (with Xrefs). The endpoint can work well with compressedUrn = true, specifying root file, after I uploaded file package in a zip.
If compressedUrn = true, that means the source file is compressed (zip), but this applies to the composite files, i.e. a main file has some dependent files. If it is a single file which has no dependent files, upload the source file directly, then call/modelderivative/v2/designdata/job without specifying compressedUrn and
rootFilename.
If I misunderstood your question, could you provide a bit more information or a demo dataset? Note, do not post any data that is confidential to your company.

Import Google app script project from JSON file

In Google Drive, it's possible to download an app script project as a .json file.
When such file is imported back to a Google Drive it's not properly associated with Google Script editor app.
Is there any way to do it properly?
Importing and exporting of Apps Script files requires the use of the import/export API.
To modify an existing script you will need to have a Oauth2 token with the scope of: https://www.googleapis.com/auth/drive.scripts
For updating a file you will "PUT" the updated JSON to:
https://www.googleapis.com/upload/drive/v2/files/{FileId}
The Apps Script file looks like
{
files:
[
{
name:{fileName},
type:{/* server_js or html */},
source:{/* source code for this file */},
id:{ /* Autogenerated. Omit this key for a new file, or leave value unmodified for an updated file */},
},
{...}
]
}
To add a file:
Add an object to the files array with the keys name, type, source
To modify a file:
Modify the values of name, type, or source of the file object but do not modify the id.
When you PUT the file back make sure you put the entire files array with your modifications, not just the new file object.
To make the modification in GAS itself would look like:
var scriptFiles = JSON.parse(downloadedJSONFile);
scriptFiles.files.push({"name":fileName,"type":fileType,"source":source});
var url = "https://www.googleapis.com/upload/drive/v2/files/"+scriptId;
var parameters = { method : 'PUT',
headers : {'Authorization': 'Bearer '+ tokenWithProperScope,
payload : JSON.stringify(scriptFiles),
contentType:'application/vnd.google-apps.script+json',
muteHttpExceptions:true};
var response = UrlFetchApp.fetch(url,parameters);
You will get a response code of 200 for a successful change. The response text will include the entire new JSON files with the assigned id to the file you added.
Fine more at:
https://developers.google.com/apps-script/import-export
Set the mimetype as application/vnd.google-apps.script

Get shared link through Google Drive API

I am working on an app using Google Drive. I want the user to be able to share files by link, setting the permissions to anyone and withLink as described in the Google Developers documentation.
However, I cannot figure out what link to share. When I share a file in the Google Drive browser interface, I see the Link to share in the format:
https://docs.google.com/presentation/d/[...]/edit?usp=sharing
A link in this format is not part of the file resource object, nor it is returned from the http call setting the permissions. I hope someone can explain to me how to get this link through the REST api?
You can use the alternateLink property in the File resource to get a link that can be shared for opening the file in the relevant Google editor or viewer:
https://developers.google.com/drive/v2/reference/files
Update
[With API V3](https://developers.google.com/drive/api/v3/reference/files it is suggested to use the webViewLink property.
To actually enable link sharing using Google Drive API:
drive.permissions.create({
fileId: '......',
requestBody: {
role: 'reader',
type: 'anyone',
}
});
Get the webLinkView value using:
const webViewLink = await drive.files.get({
fileId: file.id,
fields: 'webViewLink'
}).then(response =>
response.data.webViewLink
);
In my case using the PHP Api v3, for the link to be non-empty you must define that you request this field... and if you have the right permissions:
so something like this:
$file =self::$service->files->get("1ogXyGxcJdMXt7nJddTpVqwd6_G8Hd5sUfq4b4cxvotest",array("fields"=>"webViewLink"));
Here's a practical example on how to get the WebViewLink file property (A.K.A. File edit link):
$file = $service->files->get($file_id, array('fields' => 'webViewLink'));
$web_link_view = $file->getWebViewLink();
OR
$sheetsList = $drive_service->files->listFiles([
'fields' => 'files(id, name, webViewLink, webContentLink)',
]);
$web_link_view = $sheetsList->current()->getWebViewLink();
Pay attention that you should load the file specifying which fields you wanna bring with it (In this case, webViewLink). If you don't do that, only id and name will be available.
In case you need to adjust the file sharing settings, this is how you do it:
$permissions = new \Google_Service_Drive_Permission();
$permissions->setRole('writer');
$permissions->setType('anyone');
$drive_service->permissions->create($file_id, $permissions);
Possible values for setRole() and setType() can be found here: https://developers.google.com/drive/api/v3/reference/permissions/create
For python, I only needed to get the file "id".
Then "created" the link like this:
def create_folder(folder_name, folder_id):
"""Create a folder and prints the folder ID and Folder link
Returns : Folder Id
"""
try:
# create drive api client
service = build("drive", "v3", credentials=creds)
file_metadata = {
"name": folder_name,
"mimeType": "application/vnd.google-apps.folder",
"parents": [folder_id],
}
file = (
service.files().create(body=file_metadata, fields="id").execute()
)
id = file.get("id")
print(
f'Folder ID: "{id}".',
f'https://drive.google.com/drive/u/0/folders/{id}',
)
return id
except HttpError as error:
print(f"An error occurred: {error}")
return None