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
Related
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;
}
i want to upload video to youtube channel.i tried with following Code.the bellow code work to upload video but the problem is, i can't attach its information(Video Title,Description & Tags).after uploading it shows only video title as a "unknown" and no tags or description .i've seen CodingTofu , Dev7Dev Blog- iOS Sample Code and many other Q&A but i can't understand where i'm making mistake.
NSString* title = video.title;
NSString* description = video.videoDescription;
NSData* data = video.data;
NSMutableArray* tags = video.tags.mutableCopy;
GTLYouTubeVideo *yVideo = [GTLYouTubeVideo object];
GTLYouTubeVideoSnippet *snippet = [GTLYouTubeVideoSnippet alloc];
snippet.title = title;
snippet.descriptionProperty = description;
[tags addObject:DEFAULT_KEYWORD];
NSString* tag = [UploadController generateKeywordFromPlaylistId:UPLOAD_PLAYLIST];
[tags addObject:tag];
snippet.tags = tags;
GTLYouTubeVideoStatus *status = [GTLYouTubeVideoStatus alloc];
status.privacyStatus = #"public";
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:data MIMEType:#"video/*"];
GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosInsertWithObject:yVideo part:#"snippet,status" uploadParameters:uploadParameters];
service.uploadProgressBlock = ^(GTLServiceTicket* ticket, unsigned long long totalBytesUploaded, unsigned long long totalBytesExpectedToUpload){
CGFloat percentage = totalBytesUploaded/totalBytesExpectedToUpload;
NSLog(#"\nUploaded percentage %%(%0.2f)",percentage);
};
[service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, GTLYouTubeVideo *insertedVideo, NSError *error) {
//[waitIndicator dismissWithClickedButtonIndex:0 animated:YES];
if (error == nil)
{
NSLog(#"File ID: %#", insertedVideo.identifier);
return;
}
else
{
NSLog(#"An error occurred: %#", error);
return;
}
}];
tell me if you need any further Details
thank you.
sorry for my bad English.
i got the Mistake,
in above code, i have to add
GTLYouTubeVideo *yVideo = [GTLYouTubeVideo object];
GTLYouTubeVideoStatus *status = [GTLYouTubeVideoStatus alloc];
GTLYouTubeVideoSnippet *snippet = [GTLYouTubeVideoSnippet alloc];
*******
*******
*******
yVideo.snippet = snippet;//This part i forgot to add in my code
yVideo.status = status;//This part i forgot to add in my code
[service executeQuery........
This Might be helpful to someone who facing same issue.
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
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?
I am trying to write an application that will pull down the contents of a Google Docs file as HTML to allow me to edit it inside the app. After editing the html file I then want to upload the changes back to Google Drive and update the contents of the original Google Docs file. I have been able to pull down the Google Docs file but am not able to upload my changes back to the server.
Can you please help to understand why this error is happening ? And possibly advise me on a fix for the issue ?
I am getting the following NSError:
Error Domain=com.google.GTLJSONRPCErrorDomain Code=500 "The operation couldn’t be completed. (Internal Error)" UserInfo=0x157a8610 {error=Internal Error, GTLStructuredError=GTLErrorObject 0x16846f60: {message:"Internal Error" code:500 data:[1]}, NSLocalizedFailureReason=(Internal Error)}
2014-06-17 12:11:35.188 DrEdit[548:60b] Error UserInfo: {
GTLStructuredError = "GTLErrorObject 0x16846f60: {message:\"Internal Error\" code:500 data:[1]}";
NSLocalizedFailureReason = "(Internal Error)";
error = "Internal Error";
}
Please code being executed when uploading below:
- (void)saveFile {
GTLUploadParameters *uploadParameters = nil;
// Only update the file content if different.
if (![self.originalContent isEqualToString:self.textView.text]) {
// NSData *fileContent =
// [self.textView.text dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *s = self.textView.attributedText;
NSDictionary *documentAttributes = [NSDictionary dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType, NSDocumentTypeDocumentAttribute, nil];
NSData *htmlData = [s dataFromRange:NSMakeRange(0, s.length) documentAttributes:documentAttributes error:NULL];
// NSString *htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding];
// NSData *fileContent = [self.textView.attributedText convertToData];
uploadParameters = [GTLUploadParameters uploadParametersWithData:htmlData MIMEType:#"text/html"];
// [GTLUploadParameters uploadParametersWithData:fileContent MIMEType:#"text/plain"];
// [GTLUploadParameters uploadParametersWithData:fileContent MIMEType:#"application/vnd.google-apps.document"];
}
self.driveFile.title = self.updatedTitle;
GTLQueryDrive *query = nil;
if (self.driveFile.identifier == nil || self.driveFile.identifier.length == 0) {
// This is a new file, instantiate an insert query.
query = [GTLQueryDrive queryForFilesInsertWithObject:self.driveFile
uploadParameters:uploadParameters];
} else {
// This file already exists, instantiate an update query.
query = [GTLQueryDrive queryForFilesUpdateWithObject:self.driveFile
fileId:self.driveFile.identifier
uploadParameters:uploadParameters];
}
UIAlertView *alert = [DrEditUtilities showLoadingMessageWithTitle:#"Saving file"
delegate:self];
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFile *updatedFile,
NSError *error) {
[alert dismissWithClickedButtonIndex:0 animated:YES];
if (error == nil) {
self.driveFile = updatedFile;
self.originalContent = [self.textView.text copy];
self.updatedTitle = [updatedFile.title copy];
[self toggleSaveButton];
[self.delegate didUpdateFileWithIndex:self.fileIndex
driveFile:self.driveFile];
[self doneEditing:nil];
} else {
NSLog(#"An error occurred: %#", error);
NSLog(#"Error UserInfo: %#", error.userInfo);
[DrEditUtilities showErrorMessageWithTitle:#"Unable to save file"
message:[error description]
delegate:self];
}
}];
}
Thanks,
Michael
Its not possible to write html to a gdoc programmatically.
Currently its only possible to manually paste html but not with an api unfortunately (and strangely)
I was able to solve this problem by changing the property convert to YES on the GTLQueryDrive class. The documentation states that it will attempt to convert the file being uploaded into a native Google Docs format.
Hope this helps. Please see the method I am describing from the SDK below:
// Method: drive.files.update
// Updates file metadata and/or content
// Required:
// fileId: The ID of the file to update.
// Optional:
**// convert: Whether to convert this file to the corresponding Google Docs
// format. (Default false)**
// newRevision: Whether a blob upload should create a new revision. If false,
// the blob data in the current head revision will be replaced. (Default
// true)
// ocr: Whether to attempt OCR on .jpg, .png, or .gif uploads. (Default false)
// ocrLanguage: If ocr is true, hints at the language to use. Valid values are
// ISO 639-1 codes.
// pinned: Whether to pin the new revision. (Default false)
// setModifiedDate: Whether to set the modified date with the supplied
// modified date. (Default false)
// sourceLanguage: The language of the original file to be translated.
// targetLanguage: Target language to translate the file to. If no
// sourceLanguage is provided, the API will attempt to detect the language.
// timedTextLanguage: The language of the timed text.
// timedTextTrackName: The timed text track name.
// updateViewedDate: Whether to update the view date after successfully
// updating the file. (Default true)
// Upload Parameters:
// Maximum size: 10GB
// Accepted MIME type(s): */*
// Authorization scope(s):
// kGTLAuthScopeDrive
// kGTLAuthScopeDriveFile
// Fetches a GTLDriveFile.
+ (id)queryForFilesUpdateWithObject:(GTLDriveFile *)object
fileId:(NSString *)fileId
uploadParameters:(GTLUploadParameters *)uploadParametersOrNil;
Thanks,
Michael