Google 드라이브 앱 데이터 백업
구글 로그인
앱 데이터 읽기 및 쓰기 범위에는 Google 계정 로그인이 필요합니다. 세부 구현은 를 참조할 수 있습니다.
드라이브 API 사용
사이드 메뉴에서
Enabled APIs & Services
로 이동하여 + ENABLE APIS AND SERVICES
를 클릭합니다.검색
google drive api
.활성화
Google Drive API
를 클릭합니다.Flutter 프로젝트 구성
flutter pub add googleapis
를 실행하여 googleapis 플러그인을 프로젝트에 추가합니다.GoogleDriveAppData
라는 클래스를 만듭니다. 로그인 논리도 이 클래스에 포함됩니다. Google 드라이브의 앱 데이터 저장소를 사용할 것이므로 범위를 drive.DriveApi.driveAppdataScope
에 추가합니다.import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/drive/v3.dart' as drive;
class GoogleDriveAppData {
/// sign in with google
Future<GoogleSignInAccount?> signInGoogle() async {
GoogleSignInAccount? googleUser;
try {
GoogleSignIn googleSignIn = GoogleSignIn(
scopes: [
drive.DriveApi.driveAppdataScope,
],
);
googleUser =
await googleSignIn.signInSilently() ?? await googleSignIn.signIn();
} catch (e) {
debugPrint(e.toString());
}
return googleUser;
}
///sign out from google
Future<void> signOut() async {
GoogleSignIn googleSignIn = GoogleSignIn();
await googleSignIn.signOut();
}
}
드라이브 API를 클라이언트와 함께 사용하기 위해 드라이브 API 요청과 함께 인증 정보를 전달하기 위한
GoogleAuthClient
클래스를 생성합니다.실행
flutter pub add http
하여 http 패키지를 가져옵니다.import 'package:http/http.dart' as http;
class GoogleAuthClient extends http.BaseClient {
final Map<String, String> _headers;
final _client = http.Client();
GoogleAuthClient(this._headers);
@override
Future<http.StreamedResponse> send(http.BaseRequest request) {
request.headers.addAll(_headers);
return _client.send(request);
}
}
GoogleDriveAppData
클래스로 돌아갑니다.드라이브 클라이언트 인스턴스를 생성하는 기능을 추가합니다.
import 'package:google_drive_app_data/google_auth_client.dart';
class GoogleDriveAppData {
...
///get google drive client
Future<drive.DriveApi?> getDriveApi(GoogleSignInAccount googleUser) async {
drive.DriveApi? driveApi;
try {
Map<String, String> headers = await googleUser.authHeaders;
GoogleAuthClient client = GoogleAuthClient(headers);
driveApi = drive.DriveApi(client);
} catch (e) {
debugPrint(e.toString());
}
return driveApi;
}
}
Google 드라이브에는 특히 앱의 파일 저장을 위한 앱 데이터 폴더가 있습니다. 파일이
appDataFolder
에 저장됩니다.파일의 기본 이름을 쉽게 가져오기 위해 경로 패키지를 추가하려면 실행
flutter pub add path
하십시오.drive.File
는 드라이브가 가지고 있는 파일 정보를 저장하고 있습니다.io.File
는 장치가 가지고 있는 로컬 파일인 io 파일입니다.파일이 이전에 드라이브에 업로드된 경우
driveFileId
를 사용하여 드라이브에 최신 버전 파일을 업데이트할 수 있습니다.import 'dart:io' as io;
import 'package:path/path.dart' as path;
class GoogleDriveAppData {
...
/// upload file to google drive
Future<drive.File?> uploadDriveFile({
required drive.DriveApi driveApi,
required io.File file,
String? driveFileId,
}) async {
try {
drive.File fileMetadata = drive.File();
fileMetadata.name = path.basename(file.absolute.path);
late drive.File response;
if (driveFileId != null) {
/// [driveFileId] not null means we want to update existing file
response = await driveApi.files.update(
fileMetadata,
driveFileId,
uploadMedia: drive.Media(file.openRead(), file.lengthSync()),
);
} else {
/// [driveFileId] is null means we want to create new file
fileMetadata.parents = ['appDataFolder'];
response = await driveApi.files.create(
fileMetadata,
uploadMedia: drive.Media(file.openRead(), file.lengthSync()),
);
}
return response;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
}
ID, 버전 및 수정 시간과 같은 드라이브의 파일 정보를 얻으려면 다음 기능을 사용하여 파일 목록을 가져오고 파일 이름을 업로드된 파일과 비교할 수 있습니다.
class GoogleDriveAppData {
...
/// get drive file info
Future<drive.File?> getDriveFile(
drive.DriveApi driveApi, String filename) async {
try {
drive.FileList fileList = await driveApi.files.list(
spaces: 'appDataFolder', $fields: 'files(id, name, modifiedTime)');
List<drive.File>? files = fileList.files;
drive.File? driveFile =
files?.firstWhere((element) => element.name == filename);
return driveFile;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
}
드라이브 파일을 로컬로 다운로드하려면 다음 기능을 사용할 수 있습니다. 기본적으로 데이터 스트림을 다운로드하고 새 파일에 씁니다.
class GoogleDriveAppData {
...
/// download file from google drive
Future<io.File?> restoreDriveFile({
required drive.DriveApi driveApi,
required drive.File driveFile,
required String targetLocalPath,
}) async {
try {
drive.Media media = await driveApi.files.get(driveFile.id!,
downloadOptions: drive.DownloadOptions.fullMedia) as drive.Media;
List<int> dataStore = [];
await media.stream.forEach((element) {
dataStore.addAll(element);
});
io.File file = io.File(targetLocalPath);
file.writeAsBytesSync(dataStore);
return file;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
}
전체
GoogleDriveAppData
클래스는 다음과 같습니다.import 'dart:io' as io;
import 'package:flutter/foundation.dart';
import 'package:google_drive_app_data/google_auth_client.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/drive/v3.dart' as drive;
import 'package:path/path.dart' as path;
class GoogleDriveAppData {
/// sign in with google
Future<GoogleSignInAccount?> signInGoogle() async {
GoogleSignInAccount? googleUser;
try {
GoogleSignIn googleSignIn = GoogleSignIn(
scopes: [
drive.DriveApi.driveAppdataScope,
],
);
googleUser =
await googleSignIn.signInSilently() ?? await googleSignIn.signIn();
} catch (e) {
debugPrint(e.toString());
}
return googleUser;
}
///sign out from google
Future<void> signOut() async {
GoogleSignIn googleSignIn = GoogleSignIn();
await googleSignIn.signOut();
}
///get google drive client
Future<drive.DriveApi?> getDriveApi(GoogleSignInAccount googleUser) async {
drive.DriveApi? driveApi;
try {
Map<String, String> headers = await googleUser.authHeaders;
GoogleAuthClient client = GoogleAuthClient(headers);
driveApi = drive.DriveApi(client);
} catch (e) {
debugPrint(e.toString());
}
return driveApi;
}
/// upload file to google drive
Future<drive.File?> uploadDriveFile({
required drive.DriveApi driveApi,
required io.File file,
String? driveFileId,
}) async {
try {
drive.File fileMetadata = drive.File();
fileMetadata.name = path.basename(file.absolute.path);
late drive.File response;
if (driveFileId != null) {
/// [driveFileId] not null means we want to update existing file
response = await driveApi.files.update(
fileMetadata,
driveFileId,
uploadMedia: drive.Media(file.openRead(), file.lengthSync()),
);
} else {
/// [driveFileId] is null means we want to create new file
fileMetadata.parents = ['appDataFolder'];
response = await driveApi.files.create(
fileMetadata,
uploadMedia: drive.Media(file.openRead(), file.lengthSync()),
);
}
return response;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
/// download file from google drive
Future<io.File?> restoreDriveFile({
required drive.DriveApi driveApi,
required drive.File driveFile,
required String targetLocalPath,
}) async {
try {
drive.Media media = await driveApi.files.get(driveFile.id!,
downloadOptions: drive.DownloadOptions.fullMedia) as drive.Media;
List<int> dataStore = [];
await media.stream.forEach((element) {
dataStore.addAll(element);
});
io.File file = io.File(targetLocalPath);
file.writeAsBytesSync(dataStore);
return file;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
/// get drive file info
Future<drive.File?> getDriveFile(
drive.DriveApi driveApi, String filename) async {
try {
drive.FileList fileList = await driveApi.files.list(
spaces: 'appDataFolder', $fields: 'files(id, name, modifiedTime)');
List<drive.File>? files = fileList.files;
drive.File? driveFile =
files?.firstWhere((element) => element.name == filename);
return driveFile;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
}
결과
로그인으로 간단한 위젯을 만들고 업로드 기능을 호출해 봅시다.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GoogleDriveAppData _googleDriveAppData = GoogleDriveAppData();
GoogleSignInAccount? _googleUser;
drive.DriveApi? _driveApi;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GoogleAuthButton(
onPressed: () async {
if (_googleUser == null) {
_googleUser = await _googleDriveAppData.signInGoogle();
if (_googleUser != null) {
_driveApi =
await _googleDriveAppData.getDriveApi(_googleUser!);
}
} else {
await _googleDriveAppData.signOut();
_googleUser = null;
_driveApi = null;
}
setState(() {});
},
),
ElevatedButton(
onPressed: _driveApi != null
? () {
FilePicker.platform.pickFiles().then((value) {
if (value != null && value.files[0] != null) {
File selectedFile = File(value.files[0].path!);
_googleDriveAppData.uploadDriveFile(
driveApi: _driveApi!,
file: selectedFile,
);
}
});
}
: null,
child: Text('Save sth to drive'),
),
],
),
),
);
}
}
업로드 성공 후 드라이브 웹 포털로 이동하여 설정을 클릭하면.
사이드바에서
Manage Apps
를 선택하면 앱 목록에 앱이 나타납니다.참고: 이전 기사에서 한 번 로그인한 경우 계정에 드라이브 앱 데이터 권한이 포함되어 있지 않은 경우 파일을 업로드할 때 403이 발생할 수 있습니다. 계정에서 앱 데이터 권한을 허용하려면 한 번 로그아웃했다가 로그인하거나 다른 방법으로 계정을 허용해야 합니다.
내용이 마음에 드셨다면 지원해주세요🍖
연결🍻
Reference
이 문제에 관하여(Google 드라이브 앱 데이터 백업), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/maylau/google-drive-app-data-backup-2bnh텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)