Summary: When importing from url, user types a url for google spreadsheet, Grist will switch to Google Drive plugin to allow user to choose file manualy. Test Plan: Browser tests Reviewers: paulfitz, dsagal Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2945pull/69/head
parent
5aed22dc1e
commit
6ed1d8dfea
@ -0,0 +1,72 @@
|
||||
import {drive} from '@googleapis/drive';
|
||||
import {Readable} from 'form-data';
|
||||
import {GaxiosError, GaxiosPromise} from 'gaxios';
|
||||
import {FetchError, Response as FetchResponse, Headers} from 'node-fetch';
|
||||
|
||||
const
|
||||
SPREADSHEETS_MIMETYPE = 'application/vnd.google-apps.spreadsheet',
|
||||
XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
|
||||
export async function downloadFromGDrive(url: string) {
|
||||
const fileId = fileIdFromUrl(url);
|
||||
const googleDrive = drive("v3");
|
||||
const key = process.env.GOOGLE_API_KEY;
|
||||
if (!key) {
|
||||
throw new Error("Can't download file from Google Drive. Api key is not configured");
|
||||
}
|
||||
if (!fileId) {
|
||||
throw new Error(`Can't download from ${url}. Url is not valid`);
|
||||
}
|
||||
const fileRes = await googleDrive.files.get({
|
||||
key,
|
||||
fileId
|
||||
});
|
||||
if (fileRes.data.mimeType === SPREADSHEETS_MIMETYPE) {
|
||||
return await asFetchResponse(googleDrive.files.export(
|
||||
{ key, fileId, alt: 'media', mimeType: XLSX_MIMETYPE },
|
||||
{ responseType: 'stream' }
|
||||
));
|
||||
} else {
|
||||
return await asFetchResponse(googleDrive.files.get(
|
||||
{ key, fileId, alt: 'media' },
|
||||
{ responseType: 'stream' }
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function asFetchResponse(req: GaxiosPromise<Readable>) {
|
||||
try {
|
||||
const res = await req;
|
||||
return new FetchResponse(res.data, {
|
||||
headers: new Headers(res.headers),
|
||||
status: res.status,
|
||||
statusText: res.statusText
|
||||
});
|
||||
} catch (err) {
|
||||
const error: GaxiosError<Readable> = err;
|
||||
if (!error.response) {
|
||||
// Fetch throws exception on network error.
|
||||
// https://github.com/node-fetch/node-fetch/blob/master/docs/ERROR-HANDLING.md
|
||||
throw new FetchError(error.message, "system", error.code || "unknown");
|
||||
} else {
|
||||
// Fetch returns failure response on http error
|
||||
const resInit = error.response ? {
|
||||
status: error.response.status,
|
||||
headers: new Headers(error.response.headers),
|
||||
statusText: error.response.statusText
|
||||
} : undefined;
|
||||
return new FetchResponse(error.response.data, resInit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function isDriveUrl(url: string) {
|
||||
return !!fileIdFromUrl(url);
|
||||
}
|
||||
|
||||
function fileIdFromUrl(url: string) {
|
||||
if (!url) { return null; }
|
||||
const match = /^https:\/\/(docs|drive).google.com\/(spreadsheets|file)\/d\/([^/]*)/i.exec(url);
|
||||
return match ? match[3] : null;
|
||||
}
|
Loading…
Reference in new issue