Есть ли способ сохранить Google Doc, чтобы он имел тот же уникальный идентификатор, что и существующий документ? - PullRequest
0 голосов
/ 06 мая 2018

Мне нужно создать копию Google Doc с конкретным идентификатором - не «дружественным» именем, таким как MyDocument, а именем, которое делает его уникальным в GoogleSphere, - таким, как 1x_tfTiA9-b5UwAf3k2fg6y6hyZSYQIvhSNn-saaDs4c.

Вот сценарий, почему я хотел бы сделать это:

У меня есть новостная рассылка в форме Google Doc. Информационный бюллетень публикуется на веб-сайте путем встраивания документа в веб-страницу внутри элемента <iframe>. Точно так же публикуется аналогичная версия бюллетеня «для большого шрифта», за исключением того факта, что размер шрифта по умолчанию 24pt, а не 11pt.

Я пытаюсь автоматизировать производство крупноформатной версии, но таким образом, чтобы уникальный идентификатор крупноформатного документа не менялся, поэтому встроенный <iframe> для него все еще работает.

В прошлом я экспериментировал с процедурами Google Apps Scripts для создания глубокой копии документа, но функции глубокой копии не очень хорошо работают с изображениями и таблицами, поэтому я никогда не смог получить полную копию. Если бы я мог реализовать функцию «Сохранить как», где операндом был существующий уникальный идентификатор, я думаю, что это сделало бы то, что я хочу.

Кто-нибудь знает, как я могу это сделать?

1 Ответ

0 голосов
/ 06 мая 2018

Я углубился в это, пытаясь установить идентификатор версии «большого шрифта» файла различными способами:

  1. через copy(): var copiedFile = Drive.Files.copy(lpFile, spFile.id, options);
    что приводит к ошибке:

    Сгенерированные идентификаторы в настоящее время не поддерживаются для запросов на копирование

  2. через insert(): var newFile = Drive.Files.insert(lpFile, doc.getBlob(), options);
    что приводит к ошибке:

    Сгенерированные идентификаторы не поддерживаются для форматов Документов Google

  3. через update(): Drive.Files.update(lpFile, lpFile.id, doc.getBlob(), options);
    Этот метод успешно обновляет файл «small print» из файла small print. Эта конкретная строка, однако, использует метод Document#getBlob(), который имеет проблемы с форматированием и расширенным содержимым из Document. В частности, как вы упоминаете, изображения и таблицы не сохраняются (среди прочего, например, изменения шрифта и т. Д.). Сравните pre с post

Похоже, что - если будет найден подходящий метод экспорта отформатированного байтового содержимого из документа - метод update() наиболее перспективен. Обратите внимание, что метод update() в клиентской библиотеке Apps Script требует ввода Blob (т. Е. doc.getBlob().getBytes() не будет работать), поэтому фундаментальным ограничением может быть (отсутствие) поддержки информации расширенного формата в создаваемом Blob данные. Имея это в виду, я попробовал несколько способов получения «отформатированных» Blob данных из файла «small print»:

  1. через Document#getAs(mimetype): Drive.Files.export(lpFile, lpFile.id, doc.getAs(<type>), options);
    что не подходит для, казалось бы, разумных типов с ошибками:

    MimeType.GOOGLE_DOCS: К сожалению, произошла ошибка сервера. Пожалуйста, подождите немного и попробуйте снова.
    MimeType.MICROSOFT_WORD: преобразование из application/vnd.google-apps.document в application/vnd.openxmlformats-officedocument.wordprocessingml.document не поддерживается.

Эти ошибки имеют смысл, поскольку внутренний MimeType Документов Google не экспортируется (вы не можете «загрузить как» этот тип файла, поскольку данные сохраняются, однако Google хочет их сохранить), а также документацию для Document#getAs(mimeType) означает, что служба документов поддерживает только экспорт PDF. Действительно, попытка заставить Blob из doc.getBlob() с помощью getAs(mimeType) не удалась с ошибкой:

Преобразование из application/pdf в application/vnd.openxmlformats-officedocument.wordprocessingml.document не поддерживается.

  1. с использованием DriveApp для получения Blob вместо службы документов:
    Drive.Files.update(lpFile, lpFile.id, DriveApp.getFileById(smallPrintId).getBlob(), options);
    Это имеет те же проблемы, что и doc.getBlob(), и, вероятно, использует те же внутренние методы.

  2. при использовании DriveApp#getAs имеет те же ошибки, что и Document#getAs


Учитывая ограничения собственных реализаций Apps Script, я затем использовал расширенный сервис для получения данных Blob. Это немного сложнее, поскольку возвращаемый ресурс File на самом деле не файл, а метаданные о файле. Для получения Blob с помощью REST API необходимо экспортировать файл в желаемый MimeType. Из вышесказанного мы знаем, что формат Blob в формате PDF не может быть импортирован должным образом, поскольку этот формат использовался вышеупомянутыми попытками. Мы также знаем, что формат Google Docs не экспортируется, поэтому в MS Word осталось только .docx.

var blob = getBlobViaURL_(smallPrintId, MimeType.MICROSOFT_WORD);
Drive.Files.update(lpFile, lpFile.id, blob, options);

, где getBlobViaURL_ реализует обходной путь от этого SO вопроса для ( все еще неработающего ) Drive.Files.export() метода скрипта приложения.

Этот метод успешно обновляет существующий файл "small print" с точным содержимым из файла "small print" - по крайней мере для моего тестового документа. Учитывая, что он предполагает загрузку контента вместо использования внутренних, уже имеющихся данных, доступных для методов экспорта, он, скорее всего, не сможет работать с файлами большего размера.

Скрипт тестирования:

function copyContentFromAtoB() {
  var smallPrintId = "some id";
  var largePrintId = "some other id";

  // You must first enable the Drive "Advanced Service" before this will work.
  // Get the file metadata of the to-be-updated file.
  var lpFile = Drive.Files.get(largePrintId);
  // View available options on the relevant Drive REST API pages.
  var options = {
    updateViewedDate: false,
  };
  // Ideally this would use Drive.Files.export, but there is a bug in the Apps Script
  // client library's implementation: https://issuetracker.google.com/issues/36765129
  var blob = getBlobViaURL_(smallPrintId, MimeType.MICROSOFT_WORD);

  // Replace the contents of the large print version with that of the small print version.
  Drive.Files.update(lpFile, lpFile.id, blob, options);
}
// Below function derived from https://stackoverflow.com/a/42925916/9337071
function getBlobViaURL_(id, mimeType) {
  var url = "https://www.googleapis.com/drive/v2/files/"+id+"/export?mimeType="+ mimeType;
  var resp = UrlFetchApp.fetch(url, {
    headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken()}
  });
  return resp.getBlob();
}
...