问题描述
我想创建一个应用程序,其中某些类型的数据将同步到应用程序特定文件夹中的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.}
您需要为Google驱动器配置设置范围,
GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveAppData]
参考驱动器范围
I want to create an application in which some type of data would be sync to google drive in app specific folder and further it can be accessible to retrieve the data and populate to the app. If somehow users mobile is lost and user use another mobile and when user logged in same google account then that data should be fetch.
My problem is I am not aware the steps to follow to do this, I am able to create the app folder over google drive and this is showing to end user over drive
Now when I am trying to insert the data in it got scope error.My used code is:
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)
}
}
}
And for login and used below class is used
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 {}
Whenever I have try to upload any file the error coming:
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.}
You need to setup scope for google drive configuration,
GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveAppData]
ReferenceDrive scope
这篇关于如何访问应用程序特定的文件夹并将其用于备份或某些应用程序特定的数据?迅速的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!