我想创建一个应用程序,其中某些类型的数据将同步到应用程序特定文件夹中的Google驱动器,并且进一步可以访问该数据来检索数据并填充到该应用程序中。如果以某种方式丢失了用户手机,而用户又使用了另一台手机,并且用户登录了相同的Google帐户,则应该提取该数据。
我的问题是我不知道要执行的操作步骤,我能够在Google驱动器上创建应用程序文件夹,并且通过驱动器向最终用户显示
现在,当我尝试在其中插入数据时出现范围错误。 我使用的代码是:
import Foundation
import GoogleAPIClientForREST
enum GDriveError: Error {
case NoDataAtPath
}
class ATGoogleDrive {
private let service: GTLRDriveService
init(_ service: GTLRDriveService) {
self.service = service
}
public func listFilesInFolder(_ folder: String, onCompleted: @escaping (GTLRDrive_FileList?, Error?) -> ()) {
search(folder) { (folderID, error) in
guard let ID = folderID else {
onCompleted(nil, error)
return
}
self.listFiles(ID, onCompleted: onCompleted)
}
}
private func listFiles(_ folderID: String, onCompleted: @escaping (GTLRDrive_FileList?, Error?) -> ()) {
let query = GTLRDriveQuery_FilesList.query()
query.pageSize = 100
query.q = "'\(folderID)' in parents"
service.executeQuery(query) { (ticket, result, error) in
onCompleted(result as? GTLRDrive_FileList, error)
}
}
public func uploadFile(_ folderName: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {
search("config.json") { (folderID, error) in
if let ID = folderID {
self.upload(ID, data: data, MIMEType: MIMEType, onCompleted: onCompleted)
} else {
self.createFolder(folderName, onCompleted: { (folderID, error) in
self.upload("", data: data, MIMEType: MIMEType, onCompleted: onCompleted)
})
}
}
}
private func upload(_ parentID: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {
let metadata: GTLRDrive_File = GTLRDrive_File()
metadata.name = "config.json"
metadata.parents = ["appDataFolder"]
let uploadParameters: GTLRUploadParameters = GTLRUploadParameters(data: data, mimeType: "application/json")
uploadParameters.shouldUploadWithSingleRequest = true;
let query: GTLRDriveQuery_FilesCreate = GTLRDriveQuery_FilesCreate.query(withObject: metadata, uploadParameters: uploadParameters)//[GTLRDriveQuery_FilesCreate queryWithObject:metadata
query.fields = "id"
self.service.executeQuery(query) { (ticket, fileN, error) in
print(ticket)
print(fileN)
print(error)
if let f = fileN as? GTLRDrive_File {
if (error == nil) {
print("File ID %@", f.identifier);
} else {
print("An error occurred: %@", error);
}
}
}
}
public func listFromAppFolder(_ parentID: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {
let file = GTLRDrive_File()
file.name = "\(Date().timeIntervalSince1970)"
file.parents = ["appfolder"]
let uploadParams = GTLRUploadParameters.init(data: data, mimeType: MIMEType)
uploadParams.shouldUploadWithSingleRequest = true
let query = GTLRDriveQuery_FilesCreate.query(withObject: file, uploadParameters: uploadParams)
query.fields = "id"
self.service.executeQuery(query, completionHandler: { (ticket, file, error) in
print(ticket)
print(file)
print(error)
onCompleted?((file as? GTLRDrive_File)?.identifier, error)
})
}
public func download(_ fileID: String, onCompleted: @escaping (Data?, Error?) -> ()) {
let query = GTLRDriveQuery_FilesGet.queryForMedia(withFileId: fileID)
service.executeQuery(query) { (ticket, file, error) in
onCompleted((file as? GTLRDataObject)?.data, error)
}
}
public func search(_ fileName: String, onCompleted: @escaping (String?, Error?) -> ()) {
let query = GTLRDriveQuery_FilesList.query()
query.pageSize = 1
query.q = "name contains '\(fileName)'"
service.executeQuery(query) { (ticket, results, error) in
onCompleted((results as? GTLRDrive_FileList)?.files?.first?.identifier, error)
}
}
public func createFolder(_ name: String, onCompleted: @escaping (String?, Error?) -> ()) {
let file: GTLRDrive_File = GTLRDrive_File()
file.name = "config.json"
file.parents = ["appfolder"]
let query = GTLRDriveQuery_FilesCreate.query(withObject: file, uploadParameters: nil)
query.fields = "id"
service.executeQuery(query) { (ticket, folder, error) in
onCompleted((folder as? GTLRDrive_File)?.identifier, error)
}
}
public func delete(_ fileID: String, onCompleted: ((Error?) -> ())?) {
let query = GTLRDriveQuery_FilesDelete.query(withFileId: fileID)
service.executeQuery(query) { (ticket, nilFile, error) in
onCompleted?(error)
}
}
}
用于登录并在下面的类中使用
import UIKit
import GoogleSignIn
import GoogleAPIClientForREST
class ViewController: UIViewController {
@IBOutlet weak var resultsLabel: UILabel!
fileprivate let service = GTLRDriveService()
private var drive: ATGoogleDrive?
override func viewDidLoad() {
super.viewDidLoad()
setupGoogleSignIn()
drive = ATGoogleDrive(service)
view.addSubview(GIDSignInButton())
}
private func setupGoogleSignIn() {
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveFile]
GIDSignIn.sharedInstance().signInSilently()
}
@IBAction func uploadAction(_ sender: Any) {
if let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {
let dataImg: Data = UIImageJPEGRepresentation(UIImage(named: "logo.png")!, 1.0)!
drive?.uploadFile("config.json", data: dataImg, MIMEType: "image/png") { (fileID, error) in
print("Upload file ID: \(fileID); Error: \(error?.localizedDescription)")
}
}
}
@IBAction func listAction(_ sender: Any) {
drive?.listFilesInFolder("config.json") { (files, error) in
guard let fileList = files else {
print("Error listing files: \(error?.localizedDescription)")
return
}
self.resultsLabel.text = fileList.files?.description
print(fileList)
for nFile in fileList.files! {
if nFile.mimeType == "image/jpeg" {
self.drive?.download(nFile.identifier!, onCompleted: { (data, error) in
print(data)
print(error)
})
}
}
}
}
}
// MARK: - GIDSignInDelegate
extension ViewController: GIDSignInDelegate {
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let _ = error {
service.authorizer = nil
} else {
service.authorizer = user.authentication.fetcherAuthorizer()
service.shouldFetchNextPages = true
}
}
}
// MARK: - GIDSignInUIDelegate
extension ViewController: GIDSignInUIDelegate {}
每当我尝试上传任何文件时,都会出现错误:
Error Domain=com.google.GTLRErrorObjectDomain Code=403 "The granted scopes do not allow use of the Application Data folder." UserInfo={GTLRStructuredError=GTLRErrorObject 0x281515d10: {message:"The granted scopes do not allow use of the Application Data folder." errors:[1] code:403}, NSLocalizedDescription=The granted scopes do not allow use of the Application Data folder.}
答案 0 :(得分:3)
您需要为Google驱动器配置设置范围,
GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveAppData]
参考 Drive scope