I want to download the files from google-drive. I have fetched the GTLDriveFile objects from a drive. But downloadUrl property of these file objects are nil.
Googling more, i got that file.exportLinks also has download links. But that is also coming nil.
I used this code to fetch files:
- (void)fetchFiles {
GTLQueryDrive *query =
[GTLQueryDrive queryForFilesList];
query.maxResults = 10;
[self.service executeQuery:query
delegate:self
didFinishSelector:#selector(displayResultWithTicket:finishedWithObject:error:)];
}
- (void)displayResultWithTicket:(GTLServiceTicket *)ticket
finishedWithObject:(GTLDriveFileList *)files
error:(NSError *)error {
if (error == nil) {
if (files.items.count > 0) {
fileArr=files.items;
}
}
}
here fileArr has the files of class GTLFileDrive.
From Google-drive developer site, i got the following code snippet to download file using a parameter Url:
GTMHTTPFetcher *fetcher = [self.service.fetcherService fetcherWithURLString: urlOfFile];
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
if (error == nil) {
NSLog(#"Retrieved file content");
// Do something with data
} else {
NSLog(#"An error occurred: %#", error);
}
}];
I need the urlOfFile to complete the task.
Any help would be greatly appreciated.
When you do your initial auth, you need to request the right scope - otherwise, you only get rights to list the files, and not download them.
Something like.
NSArray *scopes = [NSArray arrayWithObjects:kGTLAuthScopeDrive, nil];
authController = [[GTMOAuth2ViewControllerTouch alloc]
initWithScope:[scopes componentsJoinedByString:#" "]
clientID:self.clientId
clientSecret:self.clientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
You can see this all in my new Google Drive Picker
https://github.com/ConfusedVorlon/HSGoogleDrivePicker
Related
After looking and finding for a shared folder that matches a given name, I need to know if that folder's creator/owner is a specific google account. How could I achieve that utilizing Google Drive's Objective-C SDK.
Here is my query that finds the shared folder given its name:
GTLQueryDrive *queryDrive = [GTLQueryDrive queryForFilesList];
queryDrive.q = #"mimeType='application/vnd.google-apps.folder' and trashed=false";
[self.service executeQuery:queryDrive completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFileList *files,
NSError *error) {
if (error == nil)
{
NSString *identifier = #"";
for(GTLDriveFile *file in files.files)
{
NSArray *tempArray = [NSArray arrayWithArray:file.owners];
NSLog(#"File Title: %# | ID: %#",file.name , file.identifier);
if ([file.name isEqualToString:#"GIVEN FOLDER NAME"]) {
identifier = file.identifier;
//How to know if the found folder is owned by a specified email?
break;
}
}
if ([identifier isEqualToString:#""]) {
[UISpinningWheelController removeSpinningWheel:self.view];
[self showAlertWithTitle:#"Error" andMessage:#"The required folder has not been shared with this Google account. Please contact the administrator."];
}
}
else {
[UISpinningWheelController removeSpinningWheel:self.view];
[self showAlertWithTitle:#"Error" andMessage:[error localizedDescription]];
}
}];
Thank you so much for your help.
I am able to upload an NSMutableString string (separated by commas) as a CSV file to Google Drive in Swift. However, I want to save it as a Google Spreadsheet.
Apparently, they have the "convert" property in Objective-C when you use queryForFilesInsertWithObject method. However, I couldn't find the Swift version of this. I created my query as such:
let query = GTLQueryDrive.queryForFilesCreateWithObject(metadata, uploadParameters: uploadParameters)
Since there is no q.convert property, I tried both of the following statements:
query.q = "convert=true"
query.q = "convert=YES"
However, none of them worked.
I have also tried to have mimeType as application/vnd.openxmlformats-officedocument.spreadsheetml.sheet and application/vnd.google-apps.spreadsheet and they didn't help either.
My code is as follows:
let data = NSMutableString()
var i = 0
repeat {
data.appendString("\(measures[i]), \(SegmentedControlChoiceValues[i])\n")
i += 1
} while i < measures.count
let dataAsString = data as String
let metadata = GTLDriveFile()
metadata.mimeType = "text/csv"
metadata.name = "Subject01.bar"
let dataToUpload = dataAsString.dataUsingEncoding(NSUTF8StringEncoding)
let uploadParameters = GTLUploadParameters(data: dataToUpload!, MIMEType: metadata.mimeType)
let query = GTLQueryDrive.queryForFilesCreateWithObject(metadata, uploadParameters: uploadParameters)
query.q = "convert=true"
Constants.service.executeQuery(query, completionHandler: { (ticket, insertedFile , error) -> Void in
if error == nil {
print("File Saved: " + metadata.name)
success(createdFileID: insertedFile.identifier)
} else {
print("An error occurred" + error.description)
success(createdFileID: "")
}
})
I would appreciate any help.
You need to upload the file first, files in the Drive API are represented by the GTLDriveFile class. The contents of the file must be fetched or uploaded separately.
You need to convert it into a portable format. When you create a new file, you specify both the initial metadata with GTLDriveFile and the content with GTLUploadParameters. Set convert property to yes for GTLQueryDrive
Try to upload and convert file to spreadsheet using this code:
GTLUploadParameters *uploadParameters = nil;
self.driveFile = [[GTLDriveFile alloc]init];
NSData *dat = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:root]];
uploadParameters =
[GTLUploadParameters uploadParametersWithData:dat MIMEType:#"text/csv"];
self.driveFile.title = #"Report.csv";
GTLQueryDrive *query = nil;
if (self.driveFile.identifier == nil || self.driveFile.identifier.length == 0)
{
query = [GTLQueryDrive queryForFilesInsertWithObject:self.driveFile
uploadParameters:uploadParameters];
query.convert = YES; // Convert file format to spread sheet
}
else
{
query = [GTLQueryDrive queryForFilesUpdateWithObject:self.driveFile
fileId:self.driveFile.identifier
uploadParameters:uploadParameters];
}
UIAlertView *alert = [DrEditUtilities showLoadingMessageWithTitle:#"While data is uploading..."
delegate:self];
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFile *updatedFile,
NSError *error)
{
appDel.File_Id = updatedFile.identifier;
[alert dismissWithClickedButtonIndex:0 animated:YES];
if (error == nil)
{
self.driveFile = updatedFile;
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Feel Fix" message:#"Successfully Uploaded" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alert show];
}
else
{
NSLog(#"An error occurred: %#", error);
[DrEditUtilities showErrorMessageWithTitle:#"Unable to save file"
message:[error description]
delegate:self];
}
}];
For more information, please check the Official Google Documentation for Google Drive API IOS: https://developers.google.com/drive/ios/reference/ios-client/interface_g_t_l_upload_parameters#properties
I tried to download file from google drive API since 3 day without success. I used this https://developers.google.com/drive/ios/devguide/files#reading_files.
But I can't understand what I need to put in *drive and *file?
I tried :
GTLDriveFile *file = #"fileText.txt"; (or I tried the url of my file on google drive...) The guide don't explain... And I didn't find real example.
GTLServiceDrive *drive = ...;
GTLDriveFile *file = ...;
NSString *url = [NSString stringWithFormat:#"https://www.googleapis.com/drive/v3/files/%#?alt=media",
file.identifier]
GTMSessionFetcher *fetcher = [drive.fetcherService fetcherWithURLString:url];
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
if (error == nil) {
NSLog(#"Retrieved file content");
// Do something with data
} else {
NSLog(#"An error occurred: %#", error);
}
}];
So I had search other code like but no one explain what I need to put in drive and file:
how to download file from google drive using objective c? (just this say it's url)
Google drive api download file for iOS
IOS: How to Download Google Docs files using ios google drive sdk API?
SOLUTION :
I had a problem of authorization with my scope, solved by total access to drive. I changed the scope (in quickstart code, look : "- (GTMOAuth2ViewControllerTouch *)createAuthController...")
-->NSArray *scopes = [NSArray arrayWithObjects:kGTLAuthScopeDrive, nil];
For download (inspired by quickstart example) :
// self.service is my GTLServiceDrive
// When the view appears, ensure that the Drive API service is authorized, and perform API calls.
- (void)viewDidAppear:(BOOL)animated {
if (!self.service.authorizer.canAuthorize) {
// Not yet authorized, request authorization by pushing the login UI onto the UI stack.
[self presentViewController:[self createAuthController] animated:YES completion:nil];
} else {
NSString *urltest = [NSString stringWithFormat:#"https://www.googleapis.com/drive/v3/files/%#?alt=media", identifier_file]; //the ID of my file in a string identifier_file
GTMSessionFetcher *fetcher = [self.service.fetcherService fetcherWithURLString:urltest]; // the request
// receive response and play it in web view:
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *errorrr) {
if (errorrr == nil) {
NSLog(#"Retrieved file content");
[webView_screen loadData:data MIMEType:#"application/pdf" textEncodingName:#"UTF-8" baseURL:nil]; //my file is a pdf
[webView_screen reload];
} else {
NSLog(#"An error occurred: %#", errorrr);
}
}];
}
}
If you want to save on the phone, you can look the Bala's code.
First fetch the file from Drive
driveFiles = [[NSMutableArray alloc] init];
for (GTLDriveFile *file in files.items) {
if ([file.mimeType isEqualToString:#"application/vnd.google-apps.folder"]) {
} else {
NSString *fileExtension = file.fileExtension;
if (fileExtension) {
if ([fileExtension isEqualToString:#"pdf"]) {
[driveFiles addObject:file];
}
}
}
}
And GTLDriveFile pass the object that you have in the array
GTLDriveFile *file=[driveFiles objectAtIndex:indexPath.row];
This is the code for download the file
NSString *link;
if (file.webContentLink) {
link = file.webContentLink;
} else if (file.embedLink) {
link = file.embedLink;
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"File has no downloadable link" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
if (link) {
NSString *downloadUrl = file.downloadUrl;
GTMHTTPFetcher *fetcher = [self.driveService.fetcherService fetcherWithURLString:downloadUrl];
//async call to download the file data
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
if (error == nil) {
if (data) {
NSString *dirPath = [self directoryPathForSavingFile];
NSString *filePath = [dirPath stringByAppendingPathComponent:file.title];
[self saveFileJSONData:data forFileName:filePath withCompletionHandler:^(BOOL successStatus) {
// Adding skip attribute to avoid data sinking in iCloud
BOOL path = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if (path) {
NSLog(#"filePath %#", filePath);
}
}];
}
} else {
NSLog(#"An error occurred: %#", error);
}
}];
}
Code for Directory path for save the file
- (NSString *)directoryPathForSavingFile:(NSString *)directoryName {
NSString *applicationDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
applicationDirectory = [applicationDirectory stringByAppendingPathComponent:directoryName];
return applicationDirectory;
}
In YouTube v2, user can report a video as inappropriate through following way,
-(void)flagInappropriateVideo: (NSString*)inVideoId
{
GDataServiceGoogleYouTube *service = [self youtubeService];
[service fetchEntryWithURL:videoEntryFetchURL completionHandler:^(GDataServiceTicket *ticket, GDataEntryBase *entry, NSError *error) {
NSError *err = error;
NSURL *complaintsLink = [[(GDataEntryYouTubeVideo*)entry complaintsLink] URL];
if(err || !entry || !complaintsLink)
{
if(!err)
err = [NSError errorWithDomain: UNKNOWN_ERROR_DOMAIN code: UNKNOWN_ERROR_CODE userInfo: nil];
}
else
{
GDataEntryYouTubeComplaint *complaint = [GDataEntryYouTubeComplaint complaintEntry];
[service fetchEntryByInsertingEntry:complaint
forFeedURL: complaintsLink
delegate:self
didFinishSelector:#selector(complaintTicket:finishedWithEntry:error:)];
}
}];
}
- (void)complaintTicket:(GDataServiceTicket *)ticket
finishedWithEntry:(GDataEntryBase *)entry
error:(NSError *)error
{
// handle completion
}
I did not find any equivalent classes and methods for GDataEntryYouTubeVideo and complaintsLink also the GDataEntryYouTubeComplaint to report a complaintEntry in YouTube V3.
I would like to know whether this is depreciated or is there any other way to do this? Please do help,Thanks!
You can see them from GDataObjectiveC client.
I'm trying to integrate Google Drive API with my iOS application. I'm unable to download files, however, and I think it has to do with the MIME type. In the API console I set the MIME types like so:
And I download files with the following code:
GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
query.q = #"mimeType = 'text/plain'";
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFileList *files,
NSError *error) {
if (error == nil) {
if (self.googleDriveFiles == nil) {
self.googleDriveFiles = [[NSMutableArray alloc] init];
}
[self.googleDriveFiles removeAllObjects];
[self.googleDriveFiles addObjectsFromArray:files.items];
NSLog(#"files: %#",self.googleDriveFiles);
[self.noteTableview reloadData];
} else {
NSLog(#"An error occurred: %#", error);
//[DrEditUtilities showErrorMessageWithTitle:#"Unable to load files"
// message:[error description]
// delegate:self];
}
}];
NSLog outputs (null) What's wrong here?