Writing a file to Google Drive?

Motivated by the ability to use an api key to write a file to dropbox, as well as the ability to write to Google Sheets, I started looking into the ability to write a file to Google Drive. I have managed to write the file, but not set the filename. My digging would suggest MATLAB does not yet support anything other than a simple upload. Simple uploads do not include any metadata, which apparently includes name. You can read more in Google's documentation for uploading a file.
I have tried doing a simple upload and then setting the name property. I have also tried first naming a file and then adding data to it. Neither have worked.
I will caution that there was quite a bit of setup in Google needed first. For the ambitious, here are the steps:
First, enable Google Drive API
  1. Navigate to https://console.developers.google.com/
  2. Click on "Create Project" button. Then click "Create".
  3. Name it and click "Create".
  4. When the main screen reloads, click "Google Drive API"
  5. Click "Create Credentials"
  6. For credential type, select "Google Drive API", and "Other UI"
  7. Provide a client id and click "Create Oauth"
  8. From Dashboard, navigate to Credentials> OAuth Consent Screen
  9. click "Add Scope"
  10. Place a check next to Google Drive API - ../auth/drive.file and click "Add"
  11. Click Save.
Next, create an API token using the RunOnce function from Matlab to Google Sheets (matlab2sheets)
  1. Run the RunOnce function. The command window will display a url and a user code.
  2. Open the url address in a browser and, where prompted, paste the code.
  3. Sign into your google account and follow on screen prompts.
  4. When it asks to allow your App to access your google account, click "Allow".
  5. You can then close the browser.
  6. Return to the command window and press any key to finish execution.
I then modified the uploadToDropbox function from Upload files to your DropBox folder from MATLAB. For brevity, I've trimmed some code here.
function output = uploadToGoogle(dropboxAccessToken,varargin)
...
dataFile = varargin{1};
...
% Read file contents
try
fid = fopen(dataFile, 'r');
data = char(fread(fid)');
fclose(fid);
catch someException
throw(addCause(MException('uploadToGoogle:unableToReadFile','Unable to read input file.'),someException));
end
% Generate the custom header
[~,remoteFName, remoteExt] = fileparts(dataFile);
headerFields = {'Authorization', ['Bearer ', dropboxAccessToken]};
headerFields{2,1} = 'Content-Type';
headerFields{2,2} = 'application/octet-stream';
headerFields = string(headerFields);
% Set the options for WEBWRITE
opt = weboptions;
opt.MediaType = 'application/octet-stream';
opt.CharacterEncoding = 'ISO-8859-1';
opt.RequestMethod = 'post';
opt.HeaderFields = headerFields;
% Upload the file
try
tempOutput = webwrite('https://www.googleapis.com/upload/drive/v3/files?uploadType=media', data, opt);
catch someException
throw(addCause(MException('uploadToGoogle:unableToUploadFile','Unable to upload file.'),someException));
end
...
This allows me to upload an untitled file - no file extension or name. If I donwload that file as is but give it the original file extension, it appears to work.
The ask, then, is if anyone can help figure out how to get the file with a name and proper extension in Google Drive?

9 Commenti

Cris LaPierre
Cris LaPierre il 13 Nov 2018
Modificato: Cris LaPierre il 13 Nov 2018
To try to upload a name first, I made the following changes:
headerFields{2,2} = 'application/json';
...
opt.MediaType = 'application/json';
...
try
mtdt = struct('name',[remoteFName remoteExt]);
ld = struct('resource', mtdt);
output1 = webwrite('https://www.googleapis.com/drive/v3/files/',ld, opt)
catch
...
However, this still uploads an untitled file, but now it is 0 bytes. Makes sense since I hadn't passed the data yet.
Cris LaPierre
Cris LaPierre il 13 Nov 2018
Modificato: Cris LaPierre il 13 Nov 2018
To try to upload the data first and then rename, I've modifided the original code in the following manner:
...
try
tempOutput = webwrite('https://www.googleapis.com/upload/drive/v3/files?uploadType=media', data, opt);
% update file name
mtdt = struct('name',[remoteFName remoteExt]);
ld = struct('resource', mtdt);
headerFields{2,2} = 'application/json';
opt.HeaderFields = headerFields;
opt.RequestMethod = 'patch';
opt.MediaType = 'application/json';
webwrite(['https://www.googleapis.com/drive/v3/files/' tempOutput.id],ld, opt)
catch someException
...
This runs without erroring out, uploads an untitled file with some size, but does not update the filename.
Raymond Guan
Raymond Guan il 27 Mag 2019
Modificato: Raymond Guan il 27 Mag 2019
I tried out your code but I'm running into a 403 error when I try to upload a file to my Google Drive. I have set up Oauth as instructed. For a sanity check, I also enabled the Sheets API and tried the matlab2sheets function, which ran perfectly. Is it still running on your end?
EDIT: Figured out my issue! Line 17 of RunOnce() must be modified from
scope_sheets = 'https://www.googleapis.com/auth/spreadsheets';
to
scope_sheets = 'https://www.googleapis.com/auth/drive.file';
Dear Cris,
Their is error in line
headerFields = string(headerFields);
I could not able to execute it. As headerFields are cell and you are converting it to String. Kindly suggest.
What's the error message? What version of MATLAB are you using?
Thanks Cris, For pointing out the matlab version clue. I have updated my matlab to 2019a and it is working fine.
For my project, I have to do following
1. Create Folder in Gdrive 2. upload encrypted image to folder created 3. Access the folder for download, when required.
I could not able to load image as error message showing octate error.
Do you have any idea on it.
Unfortunately, no i don't. The steps here connect you to Google Drive. You could look through Google Drive's API documentation to see what is possible.
I'm getting an error when running your code. I'm able to use mat2sheets without issue, and I tried changing line 17 of RunOnce.m to what was commented above. Here's the error:
Error using trytowritedatatogoogledrive
(line 27)
Unable to upload file.
Caused by:
Error using
matlab.internal.webservices.HTTPConnector/copyContentToByteArray
(line 396)
The server returned the status 401
with message "" in response to the
request to URL
https://www.googleapis.com/upload/drive/v3/files?uploadType=media.
Also, when I modified line 17 as was shown above, I got the following error. I'm super stuck, does anyone know where I might be going wrong?
Error using urlreadwrite (line 96)
Either the provided authentication method
is not supported or the username or
password provided are incorrect.
Error in urlread (line 47)
[s,status] =
urlreadwrite(mfilename,catchErrors,url,varargin{:});
Error in RunOnceDrive>getAccessToken (line
26)
deviceCodeString=urlread('https://accounts.google.com/o/oauth2/device/code','POST',
{'client_id', client_id, 'scope', scope});
Error in RunOnceDrive (line 18)
[aSheets,rSheets,tSheets] =
getAccessToken(client_id, client_secret,
scope_sheets);
I found out that your OAuth type for your Google API Credentials, needs to be "TV And Other Input Limited Devices", not Web Application. Then provide the script your client_id and client_secret and just follow the instructions.

Accedi per commentare.

 Risposta accettata

Not sure if you've figured this out already, but you can change the uploaded file name's name by slightly altering your posted code.
...
try
tempOutput = webwrite('https://www.googleapis.com/upload/drive/v3/files?uploadType=media', data, opt);
% update file name
mtdt = struct('name',[remoteFName remoteExt]);
headerFields{2,2} = 'application/json';
opt.HeaderFields = headerFields;
opt.RequestMethod = 'patch';
opt.MediaType = 'application/json';
webwrite(['https://www.googleapis.com/drive/v3/files/' tempOutput.id],mtdt, opt)
catch someException
...

8 Commenti

Awesome! Man, I was so close.
Mohammad
Mohammad il 21 Feb 2020
Hi Cris,
What do you use as input for the argument "dropboxAccessToken" in uploadToGoogle function?
KY Leng
KY Leng il 20 Mag 2020
Modificato: KY Leng il 20 Mag 2020
So, your dropboxAccessToken = "" is empty ?
I try with empty string but got error on:
headerFields = string(headerFields);
Cris LaPierre
Cris LaPierre il 20 Mag 2020
Modificato: Cris LaPierre il 27 Ago 2020
For dropboxAccessToken, I use the access token (aToken in the mat file saved by RunOnce. So the calling syntax is similar to this.
uploadToGoogle('YOUR VERY LONG ACCESS TOKEN HERE', 'c:\foobar.txt')
Since Google has made some changes on their end, here is the updated process. This worked for me today.
First, enable Google Drive API
  1. Navigate to https://console.developers.google.com/ and sign in
  2. Click "+ ENABLE APIS AND SERVICES"
  3. Locate Google Drive API in the library and click on it.
  4. Click "ENABLE"
  5. Click "Create Credentials"
  6. Click on the hyperlink for "API key" in the text.
  7. Change the API key name if you want. and click "Create"
  8. From Dashboard, navigate to OAuth Consent Screen. I had to select "External"
  9. Click Next.
  10. Give the application a name
  11. Click "Add Scope"
  12. Place a check next to Google Drive API - ../auth/drive.file and click "Add"
  13. Click Save.
Next, create an API token using the RunOnce function
  1. Run the RunOnce function. The command window will display a url and a user code
  2. Open the url address in a browser and, where prompted, paste the code.
  3. Sign into your google account and follow on screen prompts.
  4. When it asks to allow your App to access your google account, click "Allow".
  5. You can then close the browser.
  6. Return to the command window and press any key to finish execution.
RunOnce
Now upload files using the following code
uploadToGoogle(aToken, 'myScript.m')
Md Noor Islam
Md Noor Islam il 3 Ago 2020
Modificato: Md Noor Islam il 3 Ago 2020
[aToken]=RunOnce(cID,cSectret) %at first run this code to connect the app to
uploadToGoogle(aToken,'D:\Hassan\ecgTrain\ecg26393.txt')
Error:
Error using uploadToGoogle (line 57)
Unable to upload file.
Caused by:
Error using matlab.internal.webservices.HTTPConnector/copyContentToByteArray (line 396)
The server returned the status 403 with message "Forbidden" in response to the request to URL https://www.googleapis.com/upload/drive/v3/files?uploadType=media.
ecg26393.txt contains
1251X201
r1=header file
cEnd=categorical type data
is it possible to upload .txt /.mat/.csv files
Cris LaPierre
Cris LaPierre il 27 Ago 2020
Modificato: Cris LaPierre il 27 Ago 2020
It is possible. I just tested using a csv file with a header row, 80,000 rows and 23 columns.
I have utilized this tool, but am still getting an "Untilted" file in google drive. It would be nice to name the file, but my main goal is to extract the file ID so I can output a link to the file directly in a spreadsheet. Part of my Matlab scrpit outputs values to a google sheets using mat2sheets, and I would like one of the things output to be a direct link to the file I have uploaded to google drive.
Would anyone know how to exctract the file ID?

Accedi per commentare.

Più risposte (1)

Steven Remington
Steven Remington il 16 Nov 2018

0 voti

One option that you could use java in order to interface more directly with their api like in this answers post:
Mostly because MATLAB is not natively support by Google's api so it may remove some complexity that way.

Prodotti

Release

R2018b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by