如何访问应用程序特定的文件夹并将其用于备份或某些应用程序特定的数据?迅速 [英] How to access app specific folder and use it to backup or some app specific data? In swift

查看:110
本文介绍了如何访问应用程序特定的文件夹并将其用于备份或某些应用程序特定的数据?迅速的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个应用程序,其中某些类型的数据将同步到应用程序特定文件夹中的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]

Reference Drive scope

这篇关于如何访问应用程序特定的文件夹并将其用于备份或某些应用程序特定的数据?迅速的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆