blob: b73620c98d6a14ba237eb7c6b3609f4a7df44fe6 [file] [log] [blame]
// A solution for https://github.com/google/googleapis.dart/issues/366
import 'dart:async';
import 'dart:convert';
import 'dart:html';
import 'dart:typed_data';
import 'package:googleapis/drive/v3.dart' as drive;
import 'package:googleapis_auth/auth_browser.dart';
import 'package:http/browser_client.dart';
import 'web_shared.dart';
final _loginButton = querySelector('#login') as ButtonElement;
final _uploadInput = querySelector('#upload') as FileUploadInputElement;
AccessCredentials? _credentials;
Future<void> main() async {
_loginButton.onClick.listen((_) => _login());
_uploadInput.onInput.listen((_) => _upload());
}
Future<void> _login() async {
try {
_credentials = await requestAccessCredentials(
clientId: clientId().identifier,
prompt: 'consent',
scopes: [drive.DriveApi.driveFileScope],
// ignore: deprecated_member_use
logLevel: 'debug',
);
} on AuthenticationException catch (e) {
logToTextArea(e.error);
return;
}
_loginButton.disabled = _credentials != null;
_uploadInput.disabled = _credentials == null;
logToTextArea([
'logged in!',
jsonEncode(_credentials),
].join('\n'));
}
Future<void> _upload() async {
final files = _uploadInput.files;
if (files == null) {
logToTextArea('no file!');
return;
}
final client = authenticatedClient(
BrowserClient(),
_credentials!,
closeUnderlyingClient: true,
);
try {
final api = drive.DriveApi(client).files;
final options = drive.UploadOptions.resumable;
final file = files.single;
logToTextArea('starting upload');
final newFile = await api.create(
drive.File(name: 'Google APIs test file on ${DateTime.now()}'),
uploadMedia: drive.Media(file.read(options.chunkSize), file.size),
uploadOptions: options,
);
logToTextArea(jsonEncode(newFile));
logToTextArea('try to read part of the file back - asking for 11 bytes!');
// regression check for https://github.com/google/googleapis.dart/issues/462
final partialRequest = await api.get(
newFile.id!,
downloadOptions: drive.PartialDownloadOptions(drive.ByteRange(0, 10)),
) as drive.Media;
logToTextArea('bytes received: ${partialRequest.length}');
} finally {
client.close();
}
}
extension on File {
Stream<Uint8List> read(int chunkSize) async* {
if (chunkSize <= 0) {
throw ArgumentError();
}
final reader = FileReader();
// TODO: should have some error handling on reader!!
var loaded = 0;
while (loaded < size) {
final blob = slice(loaded, loaded + chunkSize);
assert(blob.size > 0);
reader.readAsArrayBuffer(blob);
await reader.onLoadEnd.first;
final bytes = reader.result as Uint8List;
loaded += bytes.length;
yield bytes;
logToTextArea(
'Finished $loaded of $size - '
'${(100 * loaded / size).toStringAsFixed(2)}%',
);
}
}
}