【问题标题】:How to save a file to Google Drive from Flutter web without a local file on disk?如何在磁盘上没有本地文件的情况下从 Flutter web 将文件保存到 Google Drive?
【发布时间】:2022-01-16 19:08:01
【问题描述】:

Drive API v3 code 示例表明,要将文件从您的应用程序保存到 Google 驱动器,您必须先在磁盘上创建一个本地文件,然后再上传。

由于我使用 Flutter for web(以及 Windows 和 Android),我无法将文件保存到磁盘。 (我也不想这样做,因为与仅通过 http 发送内存中的字节相比,它非常慢。)

如何将内存中的数据直接发送到 Google 并将其保存为文件(反之亦然)?我在 Google 搜索过的任何地方都找不到这方面的任何 Dart 代码,也找不到 Drive 示例。

【问题讨论】:

  • 从技术上讲,它是一个上传的文件流,因此数据将被编码为其文件类型。如果不是来自文件,这些数据是如何创建的?它是什么类型的数据?如果您尝试上传文件数据,那么 google docs api 或 sheet api 呢?
  • 这是一个文本文件。数据由用户在应用程序中创建。数据将存储在应用程序设置中,因此在我的问题中链接到该页面。
  • 如果我错了,请纠正我。它不是文本文件。 计算机文件存储在驱动器(例如硬盘)、磁盘(例如 DVD)和软盘(例如软盘)上,并且可能位于该介质上的文件夹(目录)中。 它的文本数据当前存储在您的应用程序的内存中。对吗?
  • 您能否编辑您的问题并提供一些我想自己尝试的代码。
  • 因此文件将是云端硬盘上的文本。然后是我应用程序中 RAM 中的对象。我还没有任何代码,因为我不知道这是否可能。我所拥有的只是我的问题中指向当前不起作用的谷歌示例的链接。

标签: flutter google-drive-api


【解决方案1】:

我知道你的问题是关于颤振的。我不是颤振开发者。在 cmets 中与您讨论过这个问题后,听起来您正在寻找是否可能。

我用 C# 进行了测试,我可以告诉你这是可能的。您所要做的就是将您的文本转换为内存流,然后上传它而不是文件流。听起来您已经将文本保存在内存流中,您应该可以上传它。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Drive.v3.Data;
using Google.Apis.Services;
using Google.Apis.Upload;

namespace ConsoleApp1
{
    class Program
    {
        static readonly string CredentialsFile = "ServiceAccountCreds.json";
        private static readonly string FileName = "UploadFileString.txt";

        static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");


            var serviceAccountCredentials = GoogleCredential.FromFile(CredentialsFile)
                .CreateScoped(DriveService.ScopeConstants.Drive);

            var service = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = serviceAccountCredentials,
                ApplicationName = "Discovery Authentication Sample",
            });

            var uploadString = "Test";
            
            // Upload file Metadata
            var fileMetadata = new Google.Apis.Drive.v3.Data.File()
            {
                Name = FileName,
                Parents = new List<string>() {"1R_QjyKyvET838G6loFSRu27C-3ASMJJa"}
            };

            // Convert raw text to memory stream for upload.
            var fsSource = new MemoryStream(Encoding.UTF8.GetBytes(uploadString ?? ""));

            string uploadedFileId;
            
            // // Create a new file on Google Drive
            // await using (var fsSource = new FileStream(FileName, FileMode.Open, FileAccess.Read))
            // await using (var fsSource = new FileStream(FileName, FileMode.Open, FileAccess.Read))
            // {
                // Create a new file, with metadata and stream.
                var request = service.Files.Create(fileMetadata, fsSource, "text/plain");
                request.Fields = "*";
                var results = await request.UploadAsync(CancellationToken.None);

                if (results.Status == UploadStatus.Failed)
                {
                    Console.WriteLine($"Error uploading file: {results.Exception.Message}");
                }

                // the file id of the new file we created
                uploadedFileId = request.ResponseBody?.Id;
            //}
        }
    }
}

理论上,任何 Flutter 示例都应该可以工作。

【讨论】:

  • 谢谢,是的,我会尽快尝试。我看到的最大挑战是,如果不将路径传递给现有文件或创建文件,我无法在 Dart 中创建 File 对象。将继续寻找那部分......
  • 这就是你不创建文件流你创建内存流的东西
【解决方案2】:

使用

dependencies:
  google_drive_client: ^1.0.3

import 'dart:io';

import 'package:dio/dio.dart';
import 'package:example/config.dart';
import 'package:flutter/material.dart';
import 'package:google_drive_client/google_drive_client.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  final GoogleDriveClient client = GoogleDriveClient(Dio(), getAccessToken: () async => Config.ACCESS_TOKEN);
  final String id = '';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ListView(
          children: [
            FlatButton(
              child: Text('list'),
              onPressed: () async {
                print(await client.list());
              },
            ),
            FlatButton(
              child: Text('create'),
              onPressed: () async {
                final File file = File((await getTemporaryDirectory()).path + '/testing2');
                file.writeAsStringSync("contents");
                var meta = GoogleDriveFileUploadMetaData(name: 'testing');
                print(await client.create(meta, file));
              },
            ),
            FlatButton(
              child: Text('delete'),
              onPressed: () async {
                await client.delete(id);
              },
            ),
            FlatButton(
              child: Text('download'),
              onPressed: () async {
                await client.download(id, 'testing');
              },
            ),
            FlatButton(
              child: Text('get'),
              onPressed: () async {
                print(await client.get(id));
              },
            ),
          ],
        ),
      ),
    );
  }
}

【讨论】:

  • 谢谢,但您不能在网络应用程序中使用 dart.io。这就是我要避免的全部事情
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-29
  • 2021-12-29
  • 2020-11-27
  • 2014-02-04
  • 1970-01-01
  • 2021-02-24
相关资源
最近更新 更多