3

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:

  1. how to download file from google drive using objective c? (just this say it's url)
  2. Google drive api download file for iOS
  3. 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.

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
G. Tommy
  • 49
  • 1
  • 6
  • which types of error is occur? – Jigar May 02 '16 at 03:32
  • The problem is more, I have no idea what i need to put in *drive and *file: a identification? what type, what identification ? where can I find it? (it's the name of the file in the drive? but how this code can find the good file in the good folder in my google drive? (I don't understand the functionement of this protocol....) – G. Tommy May 02 '16 at 05:06

1 Answers1

1

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;
}
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Bala
  • 1,224
  • 1
  • 13
  • 25
  • thank you for your answer. i tried but when i copy&paste the first the block in - (void)fetchFilesss {here for example}. - i have a problem with "for (GTLDriveFile *file in files.items)": (files not define). - and where i put the second block ? GTLDriveFile *file=[driveFiles objectAtIndex:indexPath.row]; – G. Tommy May 06 '16 at 16:14
  • Hey G.Tommy ... put - (void)fetchFilesss in ViewDidLoad method... You will get all the files ... In my code I am only fetch the PDF file from drive if([fileExtension isEqualToString:@"pdf"]) so I put this condition ... If you want all files means just remove the condition in - (void)fetchFilesss for loop. Then Using the array I show my files in Tableview. When I select the file in didSelectRowAtIndexpath I put the line GTLDriveFile *file=[driveFiles objectAtIndex:indexPath.row]; – Bala May 09 '16 at 06:59
  • Hello, with a lot of research I think I better understand your code now. However, I think it's for previous version of google drive api (v2). I say that because GTMHTTPFetcher doesn't exist in my library downloaded on official google drive api, I think now we should use GTMSessionFetcher. Also, for file.downloadUrl : downloadUrl doesn't exist... Now, i have access to file.identifier of my pdf and i use NSString *urltest = [NSString stringWithFormat:@"https://www.googleapis.com/drive/v3/files/0B-LQcMJz5Z7CUWpzekV3MnJBbWc/export?alt=media&mimeType=application"]; – G. Tommy May 22 '16 at 10:56
  • and GTMSessionFetcher *fetcher = [self.service.fetcherService fetcherWithURLString:urltest]; but an error appeared : An error occurred: Error Domain=com.google.HTTPStatus Code=403 "(null)" UserInfo={data=<7b0a2022 65727... etc... During my research i found : http://www.mzan.com/article/35546379-how-to-download-file-from-google-drive-using-objective-c.shtml and this : https://developers.google.com/drive/v3/web/manage-downloads#using_altmedia – G. Tommy May 22 '16 at 10:59
  • Documentation about error : https://developers.google.com/drive/v3/web/handle-errors#403_the_user_does_not_have_sufficient_permissions_for_file_fileid – G. Tommy May 22 '16 at 11:40
  • Thank you for your help, i find my problem and update my question. (I couldn't use your code because I don't have GTMHTTPFetcher in my librairie. – G. Tommy Jun 10 '16 at 09:19