Reputation: 431
I'm trying to get access to a pdf from a Google Drive. Whether this access is downloading or viewing, it doesn't really matter, it just needs to be available.
I am using Javascript and NodeJS, with express and google drive api.
I have the following function below which downloads a pdf. But silly me thought this was correct because it worked locally. Then when I deployed it I realised the target filepath no longer makes sense.
function downloadDoc (sourceID, targetName, callback) {
const dest = fs.createWriteStream(`${os.homedir()}/downloads/`+targetName);
drive.files.get(
{sourceID, alt: 'media'},
{responseType: 'stream'},
(err, res) => {
if (err) {
console.error(err);
}
res.data.on('end', () => {
console.log('Done downloading file.');
callback();
})
.on('error', err => {
console.error('Error downloading file.');
throw err;
})
.pipe(dest);
});
}
So what I need to do, is take the data (or response?) from this function and send it over to client side. I assume this is simple to do but, being a simple man, I find myself stuck. I have written this, with the intention that a user can click a link on client side, requesting this URL and calling the function to download the pdf.
app.get('/download_pdf', (req, res) => {
downloadDoc(documentID, 'docName.pdf', ()=>{
console.log("downloaded pdf");
});
res.end();
});
I'm thinking I need to change the argument provided to pipe() since obviously I can't use the filepath.
Similar questions I've checked:
Display Pdf in browser using express js
How to send a pdf file from Node/Express app to the browser
Send pdf via express to js client and download
While these questions are very related to this, I think my issue is due to a lack of understanding of callbacks or requests/responses. I want to learn this properly - not just ask for answers - but as it is, I'm becoming very pressed for time and need a solution soon.
Upvotes: 1
Views: 1847
Reputation: 24565
You should be able to simply pipe the returned readable stream to the express res
object (which is a writeable stream):
app.get('/download_pdf', (req, res) => {
drive.files.get({
fileId: "your-file-id-here",
alt: 'media'
})
.on('end', function () {
console.log('Done');
})
.on('error', function (err) {
console.log('Error during download', err);
})
.pipe(res);
});
Edit:
as mentioned here, drive.files.get
does return a promise. So you need to change it to:
app.get('/download_pdf', (req, res) => {
drive.files.get({
fileId,
alt: 'media'
}, {
responseType: 'stream'
}).then(response => {
response.data
.on('end', function () {
console.log('Done');
})
.on('error', function (err) {
console.log('Error during download', err);
})
.pipe(res);
});
});
Upvotes: 2
Reputation: 431
So I figured out a way. I'm not sure if this is bad practice but it seems to work. I distinguished between the two response objects by referring to one as response and one as res.
app.get('/download_pdf', (req, res) => {
const docId = req.query.id;
drive.files.get({
fileId: docId,
alt: 'media'
}, {
responseType: 'stream'
}).then(response => {
response.data
.on('end', function () {
console.log('Done');
})
.on('error', function (err) {
console.log('Error during download', err);
})
.pipe(res);
});
});
Posting this in the event that somebody else has a similar issue.
Upvotes: 0