【问题标题】:IOS: How to Download Google Docs files using ios google drive sdk API?IOS:如何使用 ios google drive sdk API 下载 Google Docs 文件?
【发布时间】:2012-11-19 09:35:05
【问题描述】:

我将 google 驱动 sdk 与我的 ios 应用程序集成。目前我正在使用以下代码根据下载 url 链接从我的谷歌驱动器 a/c 下载文件。但是,当我尝试下载 google 文档文件(具有 mime 类型 application/vnd.google-apps.document)时,google 驱动器库中没有下载 url 链接。在那种情况下,我如何下载谷歌文档数据?我可以使用 alternateLink 代替下载 url 链接吗?任何帮助都必须感谢。

我的代码:

- (void)loadFileContent {

GTMHTTPFetcher *fetcher =
[self.driveService.fetcherService fetcherWithURLString:[[self.driveFiles objectAtIndex:selectedFileIdx] downloadUrl]];

[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
    if (error == nil) {
        NSLog(@"\nfile %@ downloaded successfully from google drive", [[self.driveFiles objectAtIndex:selectedFileIdx] originalFilename]);

        //saving the downloaded data into temporary location

    } else {
        NSLog(@"An error occurred: %@", error);            

    }
}];

}

【问题讨论】:

  • 您下载文件了吗?我想知道它是如何解决的。我也在尝试下载文件,但到目前为止我找不到任何可以帮助我的资源。
  • @Shailesh,是的,我可以从谷歌驱动器下载文件。就我而言,当用户点击文件名时,我启动了下载操作。您面临什么问题?
  • 我正在使用谷歌提供的代码,他们的样本之一。项目名称是“DriveSample”,我得到的导出/下载 URL 为 NULL。完全下载失败。
  • @Shailesh,我刚刚在下面发布了我的代码,您可以查看它。通常,在获取文件列表信息时,google 还会为您提供与本地 google 文档和您的附件不同的下载 url 链接。当您知道下载 url 链接时,您可以使用该 url 启动下载操作。

标签: ios google-drive-api google-api-objc-client


【解决方案1】:

这里是从谷歌驱动器下载文件的步骤。它适用于文件和谷歌文档。

第 1 步:

获取文件列表并将其存储到带有相关文件下载链接url的数组或字典中:

- (void)loadDriveFiles {
fileFetchStatusFailure = NO;

//for more info about fetching the files check this link
//https://developers.google.com/drive/v2/reference/children/list    
GTLQueryDrive *query2 = [GTLQueryDrive queryForChildrenListWithFolderId:[parentIdList lastObject]];
query2.maxResults = 1000;

// queryTicket can be used to track the status of the request.
[self.driveService executeQuery:query2
              completionHandler:^(GTLServiceTicket *ticket,
                                  GTLDriveChildList *children, NSError *error) {
                  GTLBatchQuery *batchQuery = [GTLBatchQuery batchQuery];                      
                  //incase there is no files under this folder then we can avoid the fetching process
                  if (!children.items.count) {                          
                      [self.driveFiles removeAllObjects];
                      [fileNames removeAllObjects];                          
                      [self performSelectorOnMainThread:@selector(reloadTableDataFromMainThread) withObject:nil waitUntilDone:NO];                          
                      return ;
                  }

                  if (error == nil) {
                      int totalChildren = children.items.count;
                      count = 0;

                      [self.driveFiles removeAllObjects];
                      [fileNames removeAllObjects];                                                    //http://stackoverflow.com/questions/14603432/listing-all-files-from-specified-folders-in-google-drive-through-ios-google-driv/14610713#14610713
                      for (GTLDriveChildReference *child in children) {
                          GTLQuery *query = [GTLQueryDrive queryForFilesGetWithFileId:child.identifier];                              
                          query.completionBlock = ^(GTLServiceTicket *ticket, GTLDriveFile *file, NSError *error) {

                              //increment count inside this call is very important. Becasue the execute query call is asynchronous
                              count ++;
                              NSLog(@"Google Drive: retrieving children info: %d", count);                                  
                              if (error == nil) {
                                  if (file != nil) { //checking the file resource is available or not
                                      //only add the file info if that file was not in trash
                                      if (file.labels.trashed.intValue != 1 )
                                          [self addFileMetaDataInfo:file numberOfChilderns:totalChildren];
                                  }

                                  //the process passed all the files then we need to sort the retrieved files
                                  if (count == totalChildren) {
                                      NSLog(@"Google Drive: processed all children, now stopping HUDView - 1");
                                      [self performSelectorOnMainThread:@selector(reloadTableDataFromMainThread) withObject:nil waitUntilDone:NO];
                                  }
                              } else {
                                  //the file resource was not found
                                  NSLog(@"Google Drive: error occurred while retrieving file info: %@", error);

                                  if (count == totalChildren) {
                                      NSLog(@"Google Drive: processed all children, now stopping HUDView - 2");
                                      [self performSelectorOnMainThread:@selector(reloadTableDataFromMainThread)
                                                             withObject:nil waitUntilDone:NO];
                                  }                                      
                              }                                  
                          };                              
                          //add the query into batch query. Since we no need to iterate the google server for each child.
                          [batchQuery addQuery:query];
                      }                          
                      //finally execute the batch query. Since the file retrieve process is much faster because it will get all file metadata info at once
                      [self.driveService executeQuery:batchQuery
                                    completionHandler:^(GTLServiceTicket *ticket,
                                                        GTLDriveFile *file,
                                                        NSError *error) {
                                    }];

                      NSLog(@"\nGoogle Drive: file count in the folder: %d", children.items.count);
                  } else {
                      NSLog(@"Google Drive: error occurred while retrieving children list from parent folder: %@", error);
                  }
              }];

}

第 2 步: 添加文件元数据信息

    -(void)addFileMetaDataInfo:(GTLDriveFile*)file numberOfChilderns:(int)totalChildren
{
    NSString *fileName = @"";
    NSString *downloadURL = @"";

    BOOL isFolder = NO;

    if (file.originalFilename.length)
        fileName = file.originalFilename;
    else
        fileName = file.title;

    if ([file.mimeType isEqualToString:@"application/vnd.google-apps.folder"]) {
        isFolder = YES;
    } else {
        //the file download url not exists for native google docs. Sicne we can set the import file mime type
        //here we set the mime as pdf. Since we can download the file content in the form of pdf
        if (!file.downloadUrl) {
            GTLDriveFileExportLinks *fileExportLinks;

            NSString    *exportFormat = @"application/pdf";

            fileExportLinks = [file exportLinks];
            downloadURL = [fileExportLinks JSONValueForKey:exportFormat];
        } else {
            downloadURL = file.downloadUrl;
        }
    }

    if (![fileNames containsObject:fileName]) {
        [fileNames addObject:fileName];

        NSArray *fileInfoArray = [NSArray arrayWithObjects:file.identifier, file.mimeType, downloadURL,
                                  [NSNumber numberWithBool:isFolder], nil];
        NSDictionary *dict = [NSDictionary dictionaryWithObject:fileInfoArray forKey:fileName];

        [self.driveFiles addObject:dict];
    }
}

第 3 步: 根据表格行上的文件选择下载文件

    NSString *downloadUrl = [[[[self.driveFiles objectAtIndex:selectedFileIdx] allValues] objectAtIndex:0]
                   objectAtIndex:download_url_link];
NSLog(@"\n\ngoogle drive file download url link = %@", downloadUrl);    
GTMHTTPFetcher *fetcher =
[self.driveService.fetcherService fetcherWithURLString:downloadUrl];    
//async call to download the file data
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
    if (error == nil) {
        NSLog(@"\nfile %@ downloaded successfully from google drive", self.selectedFileName);

        //saving the downloaded data into temporary location
        [data writeToFile:<path> atomically:YES];               
    } else {
        NSLog(@"An error occurred: %@", error);
    }
}];

【讨论】:

  • 谢谢!有效。 :) 虽然我觉得,谷歌需要处理他们的 API 文档。在我们的项目中实现它的方式很复杂。另一方面,Dropbox、SkyDrive 的程序简单而直接。
  • @Shailesh,太棒了!!! :-) 是的,你是对的 :-) 当我开始集成谷歌驱动器时,我遇到了很多。
  • @loganathan 如果数据超过 1 GB,此阻止应用程序崩溃吗?
  • @MatrosovAlexander 我不确定。我没有检查这个用户案例路径。
  • 请帮助我如何在uibutton点击下载
【解决方案2】:

Google Docs 原生格式的文档不能作为其他文件下载,只能使用exportLinks URL 导出为不同的支持格式。

有关更多详细信息和支持的格式列表,请查看 Google Drive SDK 文档:

https://developers.google.com/drive/manage-downloads#downloading_google_documents

【讨论】:

【解决方案3】:

我之前也遇到过类似的问题。具体来说,我没有找到在 Google Document 中创建的原生文档的 downloadurl。它们是空的。只有通过 DrEdit 创建的(Drive SDK 中举例说明的解决方案)与 downloadUrl 相关联。

解决方案实际上是嵌入属性:GTLDriveFileExportLinks实例中的JSON,它返回NSMutableDictionary*。您可以通过访问 JSONString 属性选择查看 JSON 对象的内容。 JSON可变字典可以通过查询GTLDriveFile实例中的exportLinks得到。示例如下:

GTLDriveFile *file = files.items[0]; // assume file is assigned to a valid instance.
NSMutableDictionary *jsonDict = file.exportLinks.JSON; 
NSLog(@"URL:%@.", [jsonDict objectForKey:@"text/plain"]);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多