While testing my application at http://localhost:3000/ I was able to set up refresh_token and access_token generation. And my files attached in the form to send data are successfully sent to google drive.
Here is all my code
import formidable from 'formidable';
import fs from 'fs';
import { google } from 'googleapis'
const stream = require('stream');
const CLIENT_ID = process.env.CLIENT_ID
const CLIENT_SECRET = process.env.CLIENT_SECRET
const REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"
let REFRESH_TOKEN = process.env.REFRESH_TOKEN
let ACCESS_TOKEN = process.env.ACCESS_TOKEN
let bodyContent = `client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&grant_type=refresh_token&refresh_token=${REFRESH_TOKEN}`;
const getTokens = () => {
fetch("https://oauth2.googleapis.com/token", {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: bodyContent,
})
.then(response => {
if (response.ok) {
console.log(response)
return response.json();
} else {
throw new Error('Ошибка при выполнении запроса');
}
})
.then(data => {
console.log(data.access_token)
ACCESS_TOKEN = data.access_token;
})
.catch(error => {
console.error('Произошла ошибка:', error);
});
}
getTokens()
const auth = new google.auth.OAuth2({
CLIENT_ID,
CLIENT_SECRET,
REDIRECT_URI,
})
auth.setCredentials({ refresh_token: REFRESH_TOKEN, access_token: ACCESS_TOKEN })
const drive = google.drive({ version: 'v3', auth });
async function uploadFiles(file) {
const fileContents = fs.readFileSync(`public/${file.name}`)
const bufferStream = new stream.PassThrough()
bufferStream.end(fileContents)
try {
const response = await drive.files.create({
media: {
mimeType: 'application/pdf',
body: bufferStream
},
requestBody: {
name: file.name,
parents: ["1WZj-6PV6sschMMBUFZax-O8ImCqTE7uC"]
},
fields: 'id,name'
})
console.log(response.data)
return response.data.id;
} catch (error) {
console.error(error);
}
}
async function sendDataToGoogleSheets(body, url) {
const data = JSON.parse(body.formValues);
const sheets = google.sheets({
version: 'v4', auth
})
const urlLink = url ? `https://drive.google.com/file/d/${url}/view` : "Нет приложенного файла"
try {
const response = await sheets.spreadsheets.values.append({
spreadsheetId: "1AR32ZlUSU03QHPwRV64LyPmwhIlH5vGmLg60Ouq5mhI",
range: "A1:F1",
valueInputOption: "USER_ENTERED",
requestBody: {
values: [
[data.name, data.email, data.phoneNumber, data.comment, data.resumeLink, urlLink]
]
}
})
return response.data
} catch (error) {
console.log(error.message)
}
}
const post = async (req, res) => {
const form = new formidable.IncomingForm();
form.parse(req, async function (err, fields, files) {
let file = files ? files.file : null;
try {
if (file) {
await saveFile(file).catch(console.error);
const url = await uploadFiles(file).catch(console.error);
await sendDataToGoogleSheets(fields, url).catch(console.error);
await removeFile(file.name).catch(console.error);
} else {
await sendDataToGoogleSheets(fields).catch(console.error);
}
} catch (error) {
console.log('Failed to do shit', error.message);
res.status(500).end('Unexpected error');
}
if (err) {
res.status(err.statusCode || 500).send(err.message);
} else {
res.status(201).send('');
}
});
};
const saveFile = async (file) => {
const data = fs.readFileSync(file.path);
fs.writeFileSync(`./public/${file.name}`, data, console.log('file saved'));
await fs.unlinkSync(file.path);
return;
};
const removeFile = async (fileName) => {
await fs.unlink(`./public/${fileName}`, () => {
console.log(`file ${fileName} removed`);
});
return;
};
const reqRes = (req, res) => {
req.method === 'POST'
? post(req, res)
: req.method === 'PUT'
? console.log('PUT')
: req.method === 'DELETE'
? console.log('DELETE')
: req.method === 'GET'
? console.log('GET')
: res.status(404).send('');
};
export default reqRes;
export { config };
Then I deployed my test application to https://vercel.com/ and the files stopped being sent to google drive.
My google spreadsheets screenshot
The file is not sent to the Google spreadsheet, but the Google spreadsheet itself is filled
I tried to generate new refresh_token and access_token for the domain that vercel gave me.
But in response I get only access_token.
{ "access_token": "ХХХХХ", "expires_in": 3599, "scope": "https://www.googleapis.com/auth/drive", "token_type": "Bearer" }
In my code, to send a file to google drive, it is necessary to set the refresh_token and access_token, and this is how I pass them in the code
auth.setCredentials({ refresh_token: REFRESH_TOKEN, access_token: AСCESS_TOKEN })
But I don't receive a refresh_token at all for an application running on https://vercel.com/.
Who can tell me how to get all the necessary tokens correctly so that I can use it not only on the local host