Search code examples
fluttergoogle-drive-api

How to save a file to Google Drive from Flutter web without a local file on disk?


The example Drive API v3 code shows that to save a file to Google drive from your app you have to create a local file on disk first, then upload it.

Since I'm using Flutter for web (as well as Windows and Android) I can't save files to disk. (Nor would I want to, as it's very slow compared to just sending bytes in memory over http.)

How can I send data in memory straight to Google and have it saved as a file please (and vice versa)? I can't find any Dart code for this, nor Drive examples, anywhere that I've Googled.


Solution

  • I know your question is about flutter. I am not a flutter dev. After discussing this with you in comments it sounds like you are looking to find out if its even possible.

    I went a head and tested this with C# and i can tell you that it is possible. All you have to do is turn your text into a memory stream and then upload that instead of a file stream. As it sounds like you already have the text in a memory stream you should be able to just upload it.

    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;
                //}
            }
        }
    }
    

    In theory any of the Flutter samples should work.