1

I have a requirement to modify an existing .NET-based document generator, which today creates Word documents or HTML files. The App is moving into the cloud, and so have a full install of MS Office on every image is too complicated. So I'd like to generate GoogleDocs format documents instead, because now there's a great API which lets me do that. Except I can't find a way through the mass of options.

Plan A So far, I've managed to:

  • Create a new (empty) document
  • Re-open that document, and batch-up changes to it using the 'bachUpdate' API.

( the googledocs .net examples from https://developers.google.com/docs/api/quickstart/dotnet are helpful to get past all the authentication magic)

But my documents are usually 10s, sometimes 100s of pages long, so going back to the server, even with batches of updates, seems an unnecessary performance overhead.

Plan B For best performance, and to keep most of the existing generator code, I tried creating the whole document in the JSON style which Google requires, just as a .JSON file. I tried the example file from https://developers.google.com/docs/api/samples/output-json so I'm sure it's in a valid format.

So then I tried:

  • changing the file type to gdoc then..
  • copying it to a google drive - Google won't let me
  • uploading it to GoogleDrive: Google didn't like that either
  • I even tried uploading the HTML-format file from the exisitng generator, but it loses lots of the clever formatting which Word, and GoogleDocs, allow

So I need a way to upload a JSON file so that that Google understands its a GoogleDocs document.

How to download / upload the JSON representation of a Google doc? comes close, but doesn't quite show me the 'upload the JSON document' bit. The Google examples https://developers.google.com/docs/api/samples also only show small number of updates, not the single-file, large scale upload I need.

Am I missing something here? I seem to be so close to a working solution. Or is there a Plan C ?

Ian M
  • 11
  • 3

2 Answers2

0

It is not possible unfortunately

Although like you, I assumed it would be possible, upon further investigation and experiments I was re-reading the docs to see if I had missed anything and I saw this from the Docs API create page:

enter image description here

So unfortunately you cannot simply build a JSON representation of the document and upload it in one go. All that the API will listen to, is the title.

For example, using this code:

static void createDocFromJSON(DocsService service)
        {
            string text = File.ReadAllText("doc.json");
            Document doc = JsonSerializer.Deserialize<Document>(text);
            DocumentsResource.CreateRequest request = 
                                    service.Documents.Create(doc);
            Document createdDoc = request.Execute();
            Console.WriteLine(createdDoc.DocumentId);
        }

With this json:

{
    "Title": "Test Document",
    "Body": {
      "Content": [
        {
          "Paragraph": {
            "Elements": [
              {
                "TextRun": {
                  "Content": "Hello\n"
                }
              }
            ]
          }
        },
        {
          "Paragraph": {
            "Elements": [
              {
                "TextRun": {
                  "Content": "This is a document created from dotnet\n"
                }
              }
            ]
          }
        }
      ]
    }
  }

Will only produce a blank document with the title

:(


Use the Drive API

Yet there is hope:

Instead of generating your documents in JSON format I might suggest doing it in HTML. This would arguably be easier than creating the content > paragraph > element > text run > content type of structure that you would hypothetically need for the JSON to work. With HTML you can use h1 h2 p ul tags and more and the API will convert it to a google document format. To do this you just upload HTML file and set the MimeType as application/vnd.google-apps.document.

Adapted from the dot net library page:

https://developers.google.com/api-client-library/dotnet/guide/media_upload

static Google.Apis.Drive.v3.Data.File
        uploadFile(DriveService service, string fileToUpload)
{
    Google.Apis.Drive.v3.Data.File body = 
        new Google.Apis.Drive.v3.Data.File();
    body.Name = System.IO.Path.GetFileName(fileToUpload);
    // Set what the end mime type will be
    body.MimeType = "application/vnd.google-apps.document";
    byte[] byteArray = System.IO.File.ReadAllBytes(fileToUpload);
    
    System.IO.MemoryStream stream = 
        new System.IO.MemoryStream(byteArray);
    FilesResource.CreateMediaUpload request = 
        service.Files.Create(
            body,
            stream,
            "text/html"); // the upload format
    request.Upload();
    return request.ResponseBody;
}

which I called from the main function like:

uploadFile(service, "test.html");

Where test.html was a file in the project folder:

<h1>Hello World</h1>
<p>Document created with dotnet</p>

Which resulted in:

enter image description here

For reference, here is the repository for the dotnet library:

https://github.com/googleapis/google-api-dotnet-client

iansedano
  • 6,169
  • 2
  • 12
  • 24
  • Thanks for this - I've moved over to just the Drive API as you suggested. I can now upload their example JSON document, but I still can't get GoogleDrive to accept it as a googleDocs document. I tried giving it a filetype of .gdoc, then tried uploading the .json document and copying it with a mime type of "application/vnd.google-apps.document" as suggested elsewhere, but google says its an "invalid conversion". One thought it that my json (googledocs example) file has a DocumentID built into it. I wonder if that's the problem? – Ian M Feb 10 '21 at 15:50
  • Just tried creating a new .gdoc file using the Docs API, getting back the documentID of the new file, then pasting that into the example file's DocumentID field. No change – Ian M Feb 10 '21 at 16:06
  • also tried making the source document have a file type of.txt, as https://developers.google.com/drive/api/v3/manage-uploads#java_1 suggests that plain text to GoogleDocs is a valid conversion. Still nothing...:-( – Ian M Feb 10 '21 at 16:32
  • Well its a move in the right direction at least! Did you get the quickstart to work? When you upload a document does it appear on your drive? Can you open it in the Drive UI? – iansedano Feb 10 '21 at 16:37
  • Sure - I've got document uploading nailed! It's just that Google always opens them like a text file. So I see the JSON source. – Ian M Feb 10 '21 at 16:54
  • And the final combination: (1) create google doc, (2) edit new JSON file to have the same docID (3) UPDATE the document, not upload......and now I just see the empty document created at (1). Sigh – Ian M Feb 10 '21 at 16:58
  • What format are your files in originally? Does your document generator only output JSON? Can you add the output of your generator to the question? Do you have a choice of the output? Can't you just upload in `.doc` format for example? – iansedano Feb 12 '21 at 08:12
  • I’m not sure the format of the document is important. As a trial, I’m using one of the google example JSON files, which they say is the JSON form a doc. All i need to do is create a new document in some form which i can upload to google, and have it recognise it as a doc document. I have full control over the format of what gets uploaded, but JSON seems the cleanest. – Ian M Feb 13 '21 at 09:25
  • Can you link the example JSON? Or better yet, copy an example of what you are trying to upload into your question, that way I can test it out on my end. – iansedano Feb 13 '21 at 11:40
  • I have been using the example here: https://developers.google.com/docs/api/samples/output-json – Ian M Feb 15 '21 at 15:15
  • AFAIK that is only an output format. Also its a format that the Docs API understands, the Drive API will not automatically recognize and interpret a Doc JSON in that format. I would suggest trying uploading HTML perhaps, or just a word doc. – iansedano Feb 15 '21 at 15:41
  • Thanks - It's Word that I'm trying to avoid - if I could generate native GDOC, it will remove a huge dependency from my generator. But if you think it's output-only, then I'm doomed... Thanks for your help anyway – Ian M Feb 16 '21 at 16:09
  • Ah ok, I don't think I understood that part fully. You are not doomed though. Im going to add another answer dealing with uploading the document as JSON using the DOCS api. From the sound of it, you might need to use the Drive API for other operations like moving location or copying. – iansedano Feb 17 '21 at 09:45
  • @IanM I updated my answer with more info. Unfortunately you can't upload JSON even with the Docs API. I think the best way would be with HTML as I have demonstrated in the updated answer. – iansedano Feb 17 '21 at 13:44
  • OK - I'll try that. – Ian M Feb 18 '21 at 10:20
0

It is possible:

step 1:

use DocumentService.Create to create a new blank document. This Api call will generate a new document with a DocumentId.

step 2:

perform a BatchUpdateDocumentRequest using the documentId [1] using the InsertTextRequest [2]. This call will insert the new text into the document.

step 3:

format the document with additional BatchUpdateDocumentRequests.

[1] https://pkg.go.dev/google.golang.org/api/docs/v1#BatchUpdateDocumentRequest
[2] https://pkg.go.dev/google.golang.org/api/docs/v1#InsertTextRequest

Please look at https://github.com/prr123/gdoc/blob/master/CvtTxtToGdoc.go to see an example.

prr
  • 54
  • 1
  • 8