Как передать файл pdf через API Google Docs из nodejs (без сохранения файла)? - PullRequest
1 голос
/ 25 мая 2019

Я пытаюсь передать файл PDF через сервер Nodejs Express из API Google Docs (для контекста это резюме).Я могу сделать это с помощью HTML, текстовых и RTF-файлов легко.Я не могу сделать это с помощью PDF и других форматов, таких как zip, doc (возможно, потому что они являются двоичными типами файлов)

macOS Mojave |nodejs v10.15.0 |express.js v4.17.0 |Chrome v74.0.3729.157


Первоначально я установил API Google Docs и вызвал функцию drive.files.export с text / plain, а затем передал result.data (строка текста моего простого текста).резюме) в res.send.Это сработало √

Далее я сделал то же самое, но я установил заголовки res.setHeader("Content-disposition", "attachment; filename=resume.txt");, и снова это сработало;Я мог бы загрузить текстовый файл в моем браузере.√

Я попробовал то же самое еще раз, на этот раз передав «application / rtf» в Google Docs API, а затем установив соответствующие заголовки в своем ответе, и я смог получить версию моего резюме в формате rtf.√

Вот где у меня перестали работать ...

Следующим логическим шагом было сделать то же самое с PDF, установив все заголовки, как я сделал с RTF.Загруженный файл был примерно того размера, который я ожидал, и я не получил никаких ошибок в Nodejs, но файл был недействительным (его нельзя открыть ни в одном приложении).Я попробовал то же самое с .doc, .zip и парой других.Не повезло.

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

Большинство других ресурсов объясняют, как загружать общедоступные pdf-файлы из общедоступной папки на сервере.Также не то, что мне нужно.

Когда я консоль регистрирую объект ответа из Документов Google, я получаю объект, который содержит набор заголовков запроса и метаданных файла, а также объект «данные»со всеми необработанными данными.Данные текстовых форматов выглядели так, как и ожидалось, как данные, читаемые человеком, а данные двоичных форматов выглядели как бред, как и ожидалось.

Самое близкое, что я получил к любому прогрессу, было, когда я экспериментировал с форматом .zip и смогскачайте zip-архив, который я мог (только) распаковать через терминал, он мог бы создать пустой файл, но, по крайней мере, с правильным именем.Вероятно, это связано с тем, что zip-файл содержит простые текстовые инструкции о файлах, которые он содержит, и поэтому не был поврежден.


Рабочий пример кода для файлов RTF:

router.get("/rtf", (req, res) => {
  const docData = googleapi.getGoogleDocs("application/rtf");
  docData.then(dd => {
    res.setHeader("Content-Type", "application/rtf");
    res.setHeader("Content-Disposition", "attachment; filename=resume.rtf");
    res.send(dd.data);
  });
});
// ... some auth stuff, Promises, etc ...
getGoogleDocs(mimeType) {
  return drive.files
    .export({
      fileId: "XxXxXxXxXxXxXxXxXxXxXxXxXxXxXx",
      mimeType: mimeType
    })
    .then(fileData => {
      return fileData;
    });
}

Я пробовал несколько разных вещей, чтобы добиться того же успеха с PDF.Практически все комбинации приводят к тому, что загруженный файл является недействительным / поврежденным:

router.get("/pdf", (req, res) => {
  const docData = googleapi.getGoogleDocs("application/pdf");
  docData.then(dd => {
    // Tried various headers:
    res.setHeader("Content-Type", "application/pdf");
    // res.setHeader("Content-Type", "application/octet-stream");
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=resume_html.zip"
    );
    // Setting the content length based on the meta-data from
    // the Google Docs API payload
    res.setHeader("Content-Length", "476");
    // Tried various ways to send the response:
    // res.setHeader("Content-Transfer-Encoding", "binary");
    res.end(dd.data, "binary");
  });
});

.. и измененный код вызова API Google Docs ...

  const aPromise = new Promise((resolve, reject) => {
    drive.files.export(
      {
        fileId: "XxXxXxXxXxXxXxXxXxXxXxXxXxXxXx",
        mimeType: mimeType
      },
      { encoding: null },
      (err, buffer) => {
        // There were no errors.
        err ? reject(err) : resolve(buffer);
        // return buffer;
      }
    );
  });
  return aPromise;

Было предложено добавить 'encoding: null' как способ предотвращения повреждения двоичных данных.Я не уверен, как это могло бы помочь, учитывая, что данные находятся внутри объекта ответа в строковом формате.


Ожидаемый результат: я могу загрузить рабочий файл PDF.

Фактический результат:Я получаю файл, который содержит данные, полученные из API Google Docs, предположительно необработанные данные PDF, но не приводит к загрузке действительного / распознаваемого файла PDF.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...