NodeJS Google Drive API, как обновить файл - PullRequest
0 голосов
/ 25 марта 2019

Здравствуйте, я пытаюсь обновить Google Doc с помощью NodeJS, используя Google Drive API, и получаю эту ошибку:

{
 "error": {
  "code": 500,
  "message": null
 }
}

Вот соответствующий код:

var j = new google.auth.JWT(
    creds.client_email,
    null,
    creds.private_key,
    [
        "https://www.googleapis.com/auth/drive"
    ]
);
async function refreshTokens() {
    startedWaiting = true;
    return j.authorize((r,t) => {
        startedWaiting = false;
        timeTillNeedRefresh = t["expiry_date"] - Date.now();
        setTimeout(function() {
            refreshTokens();
        //    console.log("doing Q", Q);

        }, timeTillNeedRefresh);

        tokens = t;
        console.log("GOT A TOKEN", tokens);
        Q.forEach(x=>x());
        Q = [];

    });
}

async function start() {
    await refreshTokens();
}
start();
function myFetch(opts) {
    if(!opts) opts = {};
    var cb = opts.cb || empty;
    var headers =  {
        'Accept-Encoding': 'gzip',
        'User-Agent': 'google-api-nodejs-client/0.7.2 (gzip)',
        Authorization:tokens.token_type +" "+ tokens.access_token,
        Accept:"application/json"
    };
    if(opts.headers) {
        for(k in opts.headers) {
            headers[k] = opts.headers[k];
        }
    }
    fetch(
        opts.url 
        || "",
    {
        method:opts.method || "GET",
        headers: headers
    })
        .then(res => res.text())
        .then(body => {
            cb(body);

        });
}

updateFile({
    id: "1vebqOamZ9QB4HqfUaQN-U9Zt4y33eij-I21glMvaPVQ",
    content: "hi there"
});

async function allFuncs(tmp) {
    if(tokens === null) {
        console.log("DOING it later")
        Q.push(tmp);
        await refreshTokens();
    } else if(startedWaiting || timeTillNeedRefresh <= 0) {
        console.log("NOT for a while");
        Q.push(tmp);
    } else {
        console.log("THIS is what should happen");
        start = Date.now();
        tmp();
    }
}

async function updateFile(opts) {
    var id = opts.id,
        content = opts.content || "";
    if(id) {
        allFuncs(() => {
            myFetch({
                url:`https://www.googleapis.com/upload/drive/v3/files/${id}?uploadType=media`,
                method:"PATCH",
                headers: {
                    body: opts.content,
                    "Content-Type": "application/vnd.google-apps.document"
                },
                cb(b) {
                    console.log(b, "DID I DO IT?!");
                }
            });
        });
    }
}

Я попытался выяснить, что означает эта ошибка, но не смог найти ничего, связанного с nodejs ... Кто-нибудь знает, если это проблема с заголовком или есть ли способ ее исправить?

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

ПОЭТОМУ, если электронная почта с ключом службы имеет права на редактирование файла, она должна иметь возможность редактировать ее по своему желанию.

1 Ответ

0 голосов
/ 30 марта 2019
  • Вы хотите перезаписать существующий документ Google текстом hi there с помощью Drive API, используя служебную учетную запись.
  • Документ Google используется совместно с учетной записью службы.
  • Вы можете использовать googleapis.

Я мог бы понять, как выше. Если мое понимание верно, как насчет этого примера сценария? В этом примере сценария я использовал метод files.update Drive API.

Пример сценария:

Перед запуском сценария укажите путь к файлу json, загружаемый при создании учетной записи службы. И, пожалуйста, подтвердите идентификатор файла документа Google, снова.

const stream = require('stream');
const {google} = require('googleapis');
const creds = require('###'); // Please set the json file path downloaded when the Service Account is created.
const jwtClient = new google.auth.JWT(
    creds.client_email,
    null,
    creds.private_key,
    ['https://www.googleapis.com/auth/drive'],
    null
);

const id = "1vebqOamZ9QB4HqfUaQN-U9Zt4y33eij-I21glMvaPVQ"; // Please set the file ID of Google Document
const content = "hi there"; // Please set the text.

const drive = google.drive({version: 'v3', auth: jwtClient});
const buf = new Buffer(content, 'binary');
const buffer = Uint8Array.from(buf);
var bufferStream = new stream.PassThrough();
bufferStream.end(buffer);
const media = {
    mimeType: 'application/vnd.google-apps.document',
    body: bufferStream,
};
drive.files.update({
    fileId: id,
    media: media,
}, (err, res) => {
    if (err) {
        console.log(err);
        return;
    }
    console.log(res.data);
});

Примечание:

  • При запуске сценария существующий Документ Google перезаписывается. Поэтому, пожалуйста, будьте осторожны с этим. Я рекомендую использовать образец Документа для тестирования.
  • Если этот скрипт не работает, пожалуйста, подтвердите следующие пункты.
    1. Drive API включен на консоли API.
    2. Можно использовать сервисную учетную запись.
    3. Документ Google используется совместно с учетной записью службы.
    4. Последняя версия googleapis.

Справка:

Edit:

  • Вы не хотите использовать googleapis.
  • Вы хотите перезаписать Документ Google текстовым значением без использования googleapis.

Из ваших комментариев я понял, как и выше. Если мое понимание верно, как насчет этого примера сценария? При запуске этого скрипта, пожалуйста, подтвердите следующие пункты.

  1. О сценарии,
    • Пожалуйста, установите privateKey и clientEmail из файла JSON учетной записи службы.
    • Установите идентификатор файла существующего документа Google, который вы хотите перезаписать.
  2. Drive API включен на консоли API.
  3. Можно использовать сервисную учетную запись.
  4. Документ Google используется совместно с учетной записью службы.
  5. Последняя версия googleapis.

Пример сценария:

const cryptor = require('crypto');
const request = require('request');

// Get access token using Service Account
function getAccessToken(serviceAccount) {
    const scopes = ["https://www.googleapis.com/auth/drive"];
    const url = "https://www.googleapis.com/oauth2/v4/token";
    const header = {
        alg: "RS256",
        typ: "JWT",
    };
    const now = Math.floor(Date.now() / 1000);
    const claim = {
        iss: serviceAccount.clientEmail,
        scope: scopes.join(" "),
        aud: url,
        exp: (now + 3600).toString(),
        iat: now.toString(),
    };
    const signature = Buffer.from(JSON.stringify(header)).toString('base64') + "." + Buffer.from(JSON.stringify(claim)).toString('base64');
    var sign = cryptor.createSign('RSA-SHA256');
    sign.update(signature);
    const jwt = signature + "." + sign.sign(serviceAccount.privateKey, 'base64');
    return new Promise(function(resolve, reject) {
        request({
            method: "post",
            url: url,
            body: JSON.stringify({
                assertion: jwt,
                grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
            }),
        }, (err, res, body) => {
            if (err) {
                console.log(err);
                return;
            }
            const obj = JSON.parse(body);
            resolve(obj.access_token);
        });
    });
}

// Overwrite file in Google Drive
function overWriting(object) {
    const metadata = {
        mimeType: "application/vnd.google-apps.document",
    };
    const url = "https://www.googleapis.com/upload/drive/v3/files/" + object.googleDocumentFileId + "?uploadType=multipart";
    const boundary = "xxxxxxxxxxx";
    var data = "--" + boundary + "\r\n";
    data += "Content-Disposition: form-data; name=\"metadata\"\r\n";
    data += "Content-Type: application/json; charset=UTF-8\r\n\r\n";
    data += JSON.stringify(metadata) + "\r\n";
    data += "--" + boundary + "\r\n";
    data += "Content-Disposition: form-data; name=\"file\"; filename=\"sample.txt\"\r\n";
    data += "Content-Type: text/plain" + "\r\n\r\n";
    const payload = Buffer.concat([
        Buffer.from(data, "utf8"),
        new Buffer(object.textData, 'binary'),
        Buffer.from("\r\n--" + boundary + "--", "utf8"),
    ]);
    const options = {
        method: 'patch',
        url: url,
        headers: {
            "Content-Type": "multipart/related; boundary=" + boundary,
            'Authorization': 'Bearer ' + object.accessToken,
        },
        body: payload,
    };
    request(options, (error, response, body) => {
        console.log(body);
    });

}

async function main() {
    const serviceAccount = {
        privateKey: "###", // private_key of JSON file retrieved by creating Service Account
        clientEmail: "###", // client_email of JSON file retrieved by creating Service Account
    };
    var object = {
        googleDocumentFileId: "###", // Set the file ID of the existing Google Document
        textData: "hi there",
    };
    const accessToken = await getAccessToken(serviceAccount);
    if (accessToken) {
        object.accessToken = accessToken;
        overWriting(object);
    }
}

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