ios - Google Drive - 403 权限不足,无法上传文件但无法创建文件夹

标签 ios objective-c google-drive-api

我正在尝试使用私有(private)应用数据文件夹向我的一个应用添加 Google 云端硬盘支持。我已使用 GIDSignIn 类进行登录,并将范围设置为 kGTLRAuthScopeDriveAppdata。登录后,我可以创建文件夹并获取显示文件夹存在的文件列表,然后我可以删除文件夹,文件列表显示它们已消失。但由于某种原因,当我尝试上传文件时,出现 403 错误(“用户对此文件没有足够的权限。”)。无论我尝试将文件放入应用程序数据文件夹的根目录还是放入我创建的文件夹中,都会发生这种情况。 我已经在 Google 开发者控制台中设置了一个项目。我有一个 API key ,配置为与我的应用程序的捆绑 ID 配合使用,并为其提供不受限制的 API 访问权限。 Google 云端硬盘 API 已启用。

我的代码改编自 Google 自己的示例,因此其中很多内容可能看起来非常熟悉。我已经减少了登录处理,因为它看起来工作正常。

- (instancetype) init
{
    self = [super init];
    if (!self) return nil;

    [GIDSignIn sharedInstance].clientID = (NSString *)kGoogleClientId;
        //kGoogleClientId is the ID from the developer console.
    [GIDSignIn sharedInstance].delegate = self;
    [GIDSignIn sharedInstance].scopes = @[kGTLRAuthScopeDriveAppdata];

    return self;
}


//GIDSignInDelegate method
- (void) signIn:(GIDSignIn *)signIn didSignInForUser:(GIDGoogleUser *)user withError:(NSError *)error
{   
    authenticatedUser = user;   //authenticatedUser is an instance variable
    NSLog(@"Signed in to Google Drive with user %@", user.profile.name);
    [delegate GoogleDriveDidSignIn:self];
}


- (GTLRDriveService *) driveService
{
    static GTLRDriveService *service;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,
           ^{
            service = [[GTLRDriveService alloc] init];
            service.APIKey = (NSString *)kGoogleApiKey;
                //kGoogleApiKey matches the developer console too. It has unrestricted API access and is tied to my bundle ID
            service.APIKeyRestrictionBundleID = [[NSBundle mainBundle] bundleIdentifier];

            service.shouldFetchNextPages = YES;
            service.retryEnabled = YES;
            });

    service.authorizer = authenticatedUser.authentication.fetcherAuthorizer;
        //authenticatedUser is an instance variable which stores the user information returned by
        //GIDSignIn when the user signs in

    return service;
}


- (void) createFolderNamed:(NSString *)folderName completionHandler:(void(^)(NSString *foldername, NSString *newFolderId))completionHandler
{
    GoogleDriveHandler * __weak weakself = self;
    GTLRDriveService *service = [self driveService];
    GTLRDrive_File *folder = [GTLRDrive_File object];
    folder.name = folderName;
    folder.mimeType = (NSString *)kMimeType_GoogleDriveFolder;
    folder.parents = @[@"appDataFolder"];
    GTLRDriveQuery_FilesCreate *query = [GTLRDriveQuery_FilesCreate queryWithObject:folder uploadParameters:nil];
    [service executeQuery:query completionHandler:^(GTLRServiceTicket * _Nonnull callbackTicket, id  _Nullable object, NSError * _Nullable callbackError)
        {
        if (callbackError)
            {
            NSLog(@"-createFolderNamed: callbackError: %@", callbackError.localizedDescription);
            }
        else
            {
            GTLRDrive_File *createdFolder = (GTLRDrive_File *)object;
            if ( [createdFolder.mimeType isEqualToString:(NSString *)kMimeType_GoogleDriveFolder] )
                {
                NSLog(@"Google Drive created folder named \"%@\" with identifier \"%@\" and mime-type \"%@\"", createdFolder.name, createdFolder.identifier, createdFolder.mimeType);
                }
            else
                {
                NSLog(@"Error : Attempted to create folder, but Google Drive created item named \"%@\" with identifier \"%@\" and mime-type \"%@\"", createdFolder.name, createdFolder.identifier, createdFolder.mimeType);
                }
            }
        }];
}


- (void) writeFileAtUrl:(NSURL *)source toFolderWithId:(NSString *)folderId completionHandler:(void(^)(NSString *filename, NSString *newFileId))completionHandler
{
    GoogleDriveHandler * __weak weakself = self;
    GTLRDriveService *service = [self driveService];
    GTLRDrive_File *file = [GTLRDrive_File object];
    file.name = source.lastPathComponent;
    file.mimeType = @"binary/octet-stream";
    file.parents = @[folderId];
    file.spaces = @[@"appDataFolder"];

    GTLRUploadParameters *parameters = [GTLRUploadParameters uploadParametersWithFileURL:source MIMEType:@"binary/octet-stream"];

    parameters.shouldUploadWithSingleRequest = YES;
    GTLRDriveQuery_FilesCreate *query = [GTLRDriveQuery_FilesCreate queryWithObject:file uploadParameters:parameters];
    query.fields = @"id";

    [service executeQuery:query completionHandler:^(GTLRServiceTicket * _Nonnull callbackTicket, id  _Nullable object, NSError * _Nullable callbackError)
            {
            if (callbackTicket.statusCode == 200)
                {
                GTLRDrive_File *createdFile = (GTLRDrive_File *)object;
                NSLog(@"Wrote file %@ in Google Drive folder %@", createdFile.name, folderId);
                if (completionHandler) completionHandler(createdFile.name, createdFile.identifier);
                }
            else
                {
                NSLog(@"-writeFileAtUrl:toFolderWithId:completionHandler:  status code = %li : callbackError: %@", callbackTicket.statusCode, callbackError.localizedDescription);
                }
            }];
}

举个例子,我尝试在 GIDSignIn 登录后执行此操作:

NSURL *sampleFile = [[NSBundle mainBundle] URLForResource:@"AValidTestFile" withExtension:@"png"];
if (sampleFile)
    {
    [self writeFileAtUrl:sampleFile toFolderWithId:@"appDataFolder" completionHandler:^(NSString *filename, NSString *newFileId)
                {
                NSLog(@"Uploaded file %@ with ID %@", filename, newFileId);
                }];
    }

我仍然收到 403 错误。 到目前为止,我已经阅读了多种不同编程语言的大量教程、博客文章和论坛主题。我已经多次检查了自己的代码,并添加了大量的日志语句来仔细检查所有内容,但我无法弄清楚如何拥有创建文件夹的权限,但不能将文件放入其中。


一段时间后...
如果您通过 Google Console 中的凭据向导(而不是仅仅选择 iOS 凭据,因为您正在创建 iOS 应用程序),您会收到一条消息,其中显示“无法从 iOS 安全地访问应用程序数据。请考虑选择其他平台” “并且它拒绝为您创建凭证。尽管 SDK 具有必要的常量,但这是否有可能不起作用?

最佳答案

对于那些关注我的人,我想我已经得出结论,在 iOS 中使用 appDataFolder 是行不通的。 切换到使用驱动器空间中的文件夹后,我还发现 -uploadParametersWithFileURL:MIMEType: GTLRUploadParameters 方法不起作用。当我使用它时,我会在驱动器的根目录中获得一个名为“Untitled”的文件(包含我在 GTLRDrive_File 对象中设置的文件元数据)。当我切换到 -uploadParametersWithData:MIMEType:我在正确的位置得到了正确的文件。 我想到目前为止的教训是,如果有什么东西不起作用,就假设它是 SDK 的问题。

关于ios - Google Drive - 403 权限不足,无法上传文件但无法创建文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59249452/

相关文章:

ios - 如何使用自动布局来缩放所有屏幕尺寸的 View ?

php - 如何将大型 powerpoint 文件上传到谷歌驱动器?

google-apps-script - 无法使用 Apps 脚本将图像从 Google 云端硬盘添加到 Google 表单

ios - 在nsarray中搜索最接近的值

ios - Swift 中有复选框吗?

ios - 搜索栏 - 导航栏中的取消按钮

ios - 将 .csv 文件解析为 UITextView 时出错

ios - AVAudioSession 操纵声音输出

ios - iOS中如何将相机坐标转换为经纬度

javascript - 通过脚本设置对 Team drive 文件的权限