Now I'm trying to upload file to Google Drive.
Code was built successfully, but my file didn't upload to Google Drive.
Here is my code.
-(void)uploadFileToGoogleDrive : (NSString*)fileName fileFullPath:(NSString*)filePath {
GTLDriveFile *driveFile = [GTLDriveFile object];
driveFile.mimeType = #"application/pdf";
driveFile.originalFilename = filePath;
driveFile.name = fileName;
NSString *parentId = #"root";
driveFile.parents = #[parentId];
NSData *fileContent = [[NSData alloc] initWithContentsOfFile:fileName];
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:fileContent MIMEType:#"application/pdf"];
GTLQueryDrive *query = [GTLQueryDrive queryForFilesCreateWithObject:driveFile uploadParameters:uploadParameters];
[self.service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFile *updatedFile,
NSError *error) {
if (error == nil) {
NSLog(#"\nfile uploaded into google drive");
} else {
NSLog(#"\nAn error occurred: %#", error);
}
}];
}
Error message is like this:
Error Domain=com.google.HTTPStatus Code=501 "(null)"
Please help me.
Based from this blog, error 501 occurs more likely if the client is not a Web browser - particularly if the Web server is old. In either case if the client has specified a valid request type, then the Web server is either responding incorrectly or simply needs to be upgraded.
As stated in this answer, make sure that you have permission to make changes in these two actions:
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:self.fromPath];
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithFileHandle:fileHandle MIMEType:mimeType];
GTLQueryDrive *uploadFileQuery = [GTLQueryDrive queryForFilesCreateWithObject:toFile
uploadParameters:uploadParameters];
You can also check on this related threads:
not be able to upload a file to Google Drive
Cannot upload/download files through google drive api
Related
macOS allows users to set a profile picture for their local accounts. This picture can be modified in the Accounts system preference pane and is notably displayed at login. Is there a way to access it using Cocoa or some other system framework?
The information is accessible from Open Directory, as is suggested by dscl . -read /Users/my_user_name_here having both a JPEGPhoto and a Picture attribute. The Open Directory framework is rather ancient: documentation is sparse and examples are almost inexistant, but while digging I found a Python test in an Apple repository that shows just enough how to use the API to get started. I finally came up with this:
NSData *getODImage(NSString *userName) {
ODNode *local = [ODNode nodeWithSession:ODSession.defaultSession name:#"/Local/Default" error:nil];
if (!local) {
return nil;
}
ODRecord *record = [local recordWithRecordType:kODRecordTypeUsers name:userName attributes:nil error:nil];
if (!record) {
return nil;
}
NSArray *photoAttributes = #[kODAttributeTypePicture, kODAttributeTypeJPEGPhoto];
NSDictionary *details = [record recordDetailsForAttributes:photoAttributes error:nil];
if (!details) {
return nil;
}
NSData *jpegData = [details[kODAttributeTypeJPEGPhoto] objectAtIndex:0];
if (jpegData) {
return jpegData;
}
for (NSString *picturePath in details[kODAttributeTypePicture]) {
NSData *pictureContents = [NSData dataWithContentsOfFile:picturePath];
if (pictureContents) {
return pictureContents;
}
}
return nil;
}
where userName is the result of NSUserName(). This seems to execute fast locally, but I still have it run from a concurrent queue to avoid blocking the main thread.
The picture path returned through kODAttributeTypePicture is in the global /Library directory, which is accessible for reading from the default sandbox. This is the case for all default user pictures. It might not always be true, however, so prepare for not having a picture.
Correctness-speaking, YMMV when the user is a network user; I think that you'd have to change the node from /Local/Default to something else.
I have an older application whos image upload has begun failing, the code used it below:
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
NSError * __block anError = nil;
AWSS3PutObjectRequest *por = [AWSS3PutObjectRequest new];
por.key = key;
por.bucket = bucket;
por.contentType = #"image/png";
por.contentLength = [NSNumber numberWithUnsignedLong:[UIImagePNGRepresentation(image) length]];
por.body = UIImagePNGRepresentation(image);
por.ACL = AWSS3ObjectCannedACLPublicRead;
[[AWSS3 defaultS3] putObject:por completionHandler:^(AWSS3PutObjectOutput * _Nullable response, NSError * _Nullable error) {
anError = error;
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
if (anError) {
NSException *exception = [NSException exceptionWithName:#"NoahPutObjectException" reason:[anError description] userInfo:nil];
#throw exception;
}
I can confirm the bucket has not changed and is in the correct region. The error I receive is this:
Error Domain=com.amazonaws.AWSS3ErrorDomain Code=0 "(null)" UserIn
fo={RequestId=F5B5BFDB18414371,
Bucket=BUCKETREDACTED, HostId=HOSTIDREDACTED,
Message=The bucket you are attempting to access must be addressed
using the specified endpoint. Please send all future requests to this endpoint., Code=PermanentRedirect,
Endpoint=s3.amazonaws.com}
I have updated to using the most recent pod, but still receive this error.
Looks to me like you are using "s3.amazonaws.com" as your endpoint, and you need to instead use a region-specific endpoint address like "s3-us-west-1.amazonaws.com". The correct endpoint URLs, broken down by region, can be found here: http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
I am trying to upload simple .txt file as a test. It's only 4kb. Here is my code:
-(IBAction)uploadFile:(id)sender{
if (![self.credentials canAuthorize]) {
GTMOAuth2WindowController *windowController;
windowController = [[[GTMOAuth2WindowController alloc] initWithScope:scope clientID:kClientID clientSecret:kClientSecret keychainItemName:kKeychainItemName resourceBundle:nil] autorelease];
[windowController signInSheetModalForWindow:self.window
delegate:self
finishedSelector:#selector(windowController:finishedWithAuth:error:)];
}else{
NSLog(#"Credentials already authorized.");
}
GTLDriveFile *driveFile = [GTLDriveFile object];
driveFile.title = #"myfile";
driveFile.descriptionProperty = #"Uploaded by Google Drive API test.";
driveFile.mimeType = #"text/plain";
NSData *data = [[NSFileManager defaultManager] contentsAtPath:#"/Users/Blake/Downloads/glm/util/autoexp.txt"];
GTLUploadParameters *params = [GTLUploadParameters uploadParametersWithData:data MIMEType:driveFile.mimeType];
GTLQueryDrive *query = [GTLQueryDrive queryForFilesInsertWithObject:driveFile uploadParameters:params];
NSLog(#"Starting Upload to Google Drive");
[self.progressBar setHidden:FALSE];
[self.progressBar startAnimation:sender];
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *st, GTLDriveFile *df, NSError *error){
[self.progressBar setHidden:TRUE];
if (error == nil) {
NSLog(#"File upload succeeded");
}else{
NSLog(#"Uh-oh: File upload failed");
}
}];
}
The GTMOAuth2Authentication is authorized and the completion handler block never executes.
I looked at Activity Monitor and it says my application has sent 54 packets in the beginning. So I guess something is being sent.
How can I tell what's going wrong here, if the block never finishes to give me an error?
Could someone please help me understand what I am doing wrong?
I've recently got problem with sticking on GTMOAuth2WindowController. It was unable to present self window. I spent a lot of time in debugger and found that I forget to add WebKit.framework. It was not documented explicitly and there were no any messages in runtime (minus in google dev karma)))). So, maybe your problem also in that? Try to check your frameworks set and compare it with examples shipped with GTL.
I'm working on a Google Drive integration for iOS and I've hit a snag—I need to check for the existence of a file in a folder, but I keep getting a "500 Internal Error" response no matter how I seem to put together the request. I think this should be legit:
// self.directoryDriveFile.identifier is a valid folder identifier retrieved on previous request
GTLQueryDrive *query = [GTLQueryDrive queryForChildrenListWithFolderId:self.directoryDriveFile.identifier];
// add query to specify the file we're interested in (works in Java version...)
query.q = [NSString stringWithFormat:#"title='%#' and trashed=false",
ZTCloudSyncLockFileName];
// stopping in debugger shows query.q: title='sync.lock' and trashed=false
// fire off request
[self.driveService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFileList *files,
NSError *error) {
if (error == nil) {
if ([files.items count] > 0) {
self.foundLockfile = YES;
} else {
self.foundLockfile = NO;
}
} else {
DLog(#"An error occurred loading lockfile request: %#", error);
[self bailWithError:error performCleanup:NO];
}
}];
When the query is executed, it always ends up in error, with the following unfortunately sparse error information:
Error Domain=com.google.GTLJSONRPC
ErrorDomain Code=500 "The operation couldn’t be completed. (Internal Error)"
UserInfo=0x99c4660 {
error=Internal Error,
GTLStructuredError=GTLErrorObject 0x99c4360: {
message:"Internal Error" code:500 data:[1]},
NSLocalizedFailureReason=(Internal Error)}
I've also tried the following more basic query, specifying a parents clause, but I end up with the same unfortunately spare error object shown above:
GTLQueryDrive *altQuery = [GTLQueryDrive queryForFilesList];
altQuery.q = [NSString stringWithFormat:#"title='%#' and trashed=false and '%#' in parents",
ZTCloudSyncLockFileName,
self.directoryDriveFile.identifier];
That, too, should work, but also produces a 500 error.
Additional information: tested the following while working on this:
Check for folder in directory root—OK
Create folder in directory root—OK
Check for file named sync.lock in directory root—OK
-(void)fetchGoogleDriveFileListWithfolderId:(NSString *)folderId
:(void (^)(NSMutableArray *, NSError*))completionBlock
{
GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
query.q =[NSString stringWithFormat:#"'%#' in parents and trashed=false", folderId];
GTLServiceTicket *ticketListing = [self.driveService
executeQuery:query completionHandler:^(GTLServiceTicket *ticket,GTLDriveFileList *files, NSError *error)
{
NSMutableArray *mainArray=[[NSMutableArray alloc]init];
if (error == nil)
{
completionBlock(files.items,nill);
}
else
{
NSLog(#"An error occurred: %#", error);
completionBlock(nil,error);
}
}];
}
You can use above method for fetch the folder contents.
Here folderId is
“root” (Main Drive)
“sharedWithMe” for shared folder
GTLDrivefile identifier value
I am creating a new UIManagedDocument with iCloud support as follows:
Alloc and init with local sandbox URL
Set persistent store options to support iCloud: ubiquitousContentNameKey and ubiquitousContentURL. The name I'm generating uniquely and the URL is pointing to my ubiquityContainer / CoreData.
Save locally to sandbox with UIManagedDocument's saveToURL method.
In completion handler, move to iCloud with FileManager's setUbiquitous method.
So far, this dance works. (Well, sort of). After I call setUbiquitous, I get an error that says it WASN'T successful, however the document moves to the cloud. When it's done, I have a new document in the cloud. This appears to be a bug, as I've been able to replicate it with others' code.
I'm actually generating this document in a "Documents View Controller," which lists all of the documents in the cloud. So when this new document's final completion handler is finished, it shows up in the table view thanks to an NSMetadataQuery. So far, pretty standard usage I think.
To edit a document, the user taps and goes to a "Single View Document View Controller."
In this view controller, I need to "reopen" the selected document so the user can edit it.
So I go through series of steps again:
Alloc / init a UIManagedDocument with a fileURL -- this time, the URL is from the cloud.
Set my persistent store options, same as step 2 above, with same settings.
Now, I ATTEMPT step 3, which is to open the document from disk, but it fails. The document is in a state of "Closed | SavingError" and the attempt to open fails.
Does anyone know why my document would create OK, move to the cloud OK, but then fail to open on an immediate subsequent attempt? (Really, an attempt within that launch of the app - see below). Specifically, what would make a UIManagedDocument instance be created but in a closed, non-openable state?
Interestingly enough, if I quit the app and launch again, I can tap and reload the document and edit it.
And very occasionally I can create, then open, and edit very briefly, say insert one managedobject, and then it goes into this close | saving error state.
ERROR INFO:
I've subclassed UIManagedDocument and overrode the -handleError: method to try and get more information, and here's what I get (along with some other debugging logs I put in):
2012-10-05 14:57:06.000 Foundations[23687:907] Single Document View Controller View Did Load. Document: fileURL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ documentState: [Closed]
2012-10-05 14:57:06.052 MyApp[23687:907] Document state changed. Current state: 5 fileURL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/ documentState: [Closed | SavingError]
2012-10-05 14:57:06.057 Foundations[23687:5303] UIManagedDocument error: The store name: New Document 34 is already in use.
Store URL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore
In Use Store URL: file://localhost/var/mobile/Applications/D423F5FF-4B8E-4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore
2012-10-05 14:57:06.059 MyApp[23687:5303] {
NSLocalizedDescription = "The store name: New Document 34 is already in use.\n\tStore URL: file://localhost/private/var/mobile/Library/Mobile%20Documents/7PB5426XF4~com~howlin~MyApp/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n\tIn Use Store URL: file://localhost/var/mobile/Applications/D423F5FF-4B8E-4C3E-B908-11824D70FD34/Documents/New%20Document%2034/StoreContent.nosync/persistentStore\n";
NSPersistentStoreUbiquitousContentNameKey = "New Document 34";
}
The error seems to think I'm it create a store that already exists on the subsequent opening. Am I now supposed to set those iCloud option on the persistent store on a second opening? I've tried that approach and it didn't work either.
I've studied the Stanford lectures on UIManagedDocument and don't see what I'm doing wrong.
Here's my method to create the doc and move to cloud:
- (void) testCreatingICloudDocWithName:(NSString*)name
{
NSURL* cloudURL = [self.docManager.iCloudURL URLByAppendingPathComponent:name isDirectory:YES];
NSURL* fileURL = [self.docManager.localURL URLByAppendingPathComponent:name];
self.aWriting = [[FNFoundationDocument alloc] initWithFileURL:fileURL];
[self setPersistentStoreOptionsInDocument:self.aWriting];
[self.aWriting saveToURL:fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
if (success == YES) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//create file coordinator
//move document to icloud
NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
NSError* coorError = nil;
[fileCoordinator coordinateWritingItemAtURL:cloudURL options:NSFileCoordinatorWritingForReplacing error:&coorError byAccessor:^(NSURL *newURL) {
if (coorError) {
NSLog(#"Coordinating writer error: %#", coorError);
}
NSFileManager* fm = [NSFileManager defaultManager];
NSError* error = nil;
NSLog(#"Before set ubiq");
[fm setUbiquitous:YES itemAtURL:fileURL destinationURL:newURL error:&error];
if (!error) {
NSLog(#"Set ubiquitous successfully.");
}
else NSLog(#"Error saving to cloud. Error: %#", error);
NSLog(#"State of Doc after error saving to cloud: %#", self.aWriting);
}];
});
}
}];
}
Here's where I set options for iCloud on the persistentStore:
- (void)setPersistentStoreOptionsInDocument:(FNDocument *)theDocument
{
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:[theDocument.fileURL lastPathComponent] forKey:NSPersistentStoreUbiquitousContentNameKey];
NSURL* coreDataLogDirectory = [self.docManager.coreDataLogsURL URLByAppendingPathComponent:[theDocument.fileURL lastPathComponent]];
NSLog(#"Core data log dir: %#", coreDataLogDirectory);
[options setObject:coreDataLogDirectory forKey:NSPersistentStoreUbiquitousContentURLKey];
theDocument.persistentStoreOptions = options;
}
And here's where I try to reopen it:
- (void) prepareDocForUse
{
NSURL* fileURL = self.singleDocument.fileURL;
if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
NSLog(#"File doesn't exist");
}
else if (self.singleDocument.documentState == UIDocumentStateClosed) {
// exists on disk, but we need to open it
[self.singleDocument openWithCompletionHandler:^(BOOL success) {
if (!success) {
NSError* error;
[self.singleDocument handleError:error userInteractionPermitted:NO];
}
[self setupFetchedResultsController];
}];
} else if (self.singleDocument.documentState == UIDocumentStateNormal) {
// already open and ready to use
[self setupFetchedResultsController];
}
}
Have you recently been testing various version of iOS? Try changing the title of your saved document to something other than "New Document 34", I was experiencing this same issue and I believe it had to do with conflicting documents saved from different sdk compilations of the app using the same document url.
I target iOS7, I use a single UIManagedDocument as my app DB with the goal to better integrate CoreData and iCloud as suggested by Apple in its documentation. I had the same problem, i solved with the following code.
Since I wrote it, I moved the PSC options settings inside the lazy instantiation of the UIManagedDocument.
My original code created, closed and then reopened the document using the callback with success standard functions. I found it on a book by Erika Sadun. Everything seemed ok but I couldn't reopen the just created and then closed document because it was in "savings error" state. I lost a week on it, I couldn't understand what I was doing wrong because until the reopen everything was perfect.
The following code works perfectly on my iPhone5 and iPad3.
Nicola
-(void) fetchDataWithBlock: (void (^) (void)) fetchingDataBlock
{
//If the CoreData local file exists then open it and perform the query
if([[NSFileManager defaultManager] fileExistsAtPath:[self.managedDocument.fileURL path]]){
NSLog(#"The CoreData local file in the application sandbox already exists.");
if (self.managedDocument.documentState == UIDocumentStateNormal){
NSLog(#"The CoreData local file it's in Normal state. Fetching data.");
fetchingDataBlock();
}else if (self.managedDocument.documentState == UIDocumentStateClosed){
NSLog(#"The CoreData local file it's in Closed state. I am opening it.");
[self.managedDocument openWithCompletionHandler:^(BOOL success) {
if(success){
NSLog(#"SUCCESS: The CoreData local file has been opened succesfully. Fetching data.");
fetchingDataBlock();
}else{
NSLog(#"ERROR: Can't open the CoreData local file. Can't fetch the data.");
NSLog(#"%#", self.managedDocument);
return;
}
}];
}else{
NSLog(#"ERROR: The CoreData local file has an unexpected documentState: %#", self.managedDocument);
}
}else{
NSLog(#"The CoreData local file in the application sandbox did not exist.");
NSLog(#"Setting the UIManagedDocument PSC options.");
[self setPersistentStoreOptionsInDocument:self.managedDocument];
//Create the Core Data local File
[self.managedDocument saveToURL:self.managedDocument.fileURL
forSaveOperation:UIDocumentSaveForCreating
completionHandler:^(BOOL success) {
if(success){
NSLog(#"SUCCESS: The CoreData local file has been created. Fetching data.");
fetchingDataBlock();
}else{
NSLog(#"ERROR: Can't create the CoreData local file in the application sandbox. Can't fetch the data.");
NSLog(#"%#", self.managedDocument);
return;
}
}];
}
}