Fetching data from Google Drive using Node JS [duplicate] - javascript

Im trying to get the contents of a file using the google drive API v3 in node.js.
I read in this documentation I get a stream back from drive.files.get({fileId, alt: 'media'})but that isn't the case. I get a promise back.
https://developers.google.com/drive/api/v3/manage-downloads
Can someone tell me how I can get a stream from that method?

I believe your goal and situation as follows.
You want to retrieve the steam type from the method of drive.files.get.
You want to achieve this using googleapis with Node.js.
You have already done the authorization process for using Drive API.
For this, how about this answer? In this case, please use responseType. Ref
Pattern 1:
In this pattern, the file is downloaded as the stream type and it is saved as a file.
Sample script:
var dest = fs.createWriteStream("###"); // Please set the filename of the saved file.
drive.files.get(
{fileId: id, alt: "media"},
{responseType: "stream"},
(err, {data}) => {
if (err) {
console.log(err);
return;
}
data
.on("end", () => console.log("Done."))
.on("error", (err) => {
console.log(err);
return process.exit();
})
.pipe(dest);
}
);
Pattern 2:
In this pattern, the file is downloaded as the stream type and it is put to the buffer.
Sample script:
drive.files.get(
{fileId: id, alt: "media",},
{responseType: "stream"},
(err, { data }) => {
if (err) {
console.log(err);
return;
}
let buf = [];
data.on("data", (e) => buf.push(e));
data.on("end", () => {
const buffer = Buffer.concat(buf);
console.log(buffer);
});
}
);
Reference:
Google APIs Node.js Client

Related

How to download a file with Node.js from google drive api

How to download a file with Node.js from google drive api
I don't need anything special. I only want to download a file from a GoogleDrive, and then save it to a given directory of client.
app.get("/download",function(req,res){
const p38290token = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);
p38290token.setCredentials({ refresh_token: token.acc });
const p38290Id = google.drive({
version: "v3",
auth: p38290token,
});
var dest = fs.createWriteStream("./test.png");
try {
p38290Id.files.get({
fileId: "1daaxy0ymKbMro-e-JnexmGvM4WzW-3Hn",
alt: "media"
}, { responseType: "stream" },
(err, res) => {
res.data
.on("end", () => {
console.log("Done");
})
.on("error", err => {
console.log("Error", err);
})
.pipe(dest); // i want to sent this file to client who request to "/download"
}
)
} catch (error) {
}
})
I want to do that just someone come to www.xyz.com/download and file will be download automatically
The issue seems to be with this line:
var dest = fs.createWriteStream("./test.png");
You are using a file system command which is meant to interact with files on the server. Your question makes it clear that you wish for express to deliver the contents of the file over to the client making the HTTP request.
For that you can just use the res parameter of the route callback function. You declare it on this line:
app.get("/download",function(req,res){
In your case I'd remove the dest variable completely and simply pipe the file to res like so:
.pipe(dest);
Have a look at this answer as well.

How can I concatenate streaming audio?

I have a webapp that records audio from the user's microphone. It sends the data to the server. The relevant code looks like this:
class Recorder {
// ...
setRecorder() {
this.recorder = new RecordRTC(this.stream, {
type: 'audio',
mimeType: this.mimeType,
recorderType: StereoAudioRecorder,
timeSlice: 2000, // Interval to send recorded data
ondataavailable: async blob => { // send the data to the server
let seq = this.seq++
let data = await blob.arrayBuffer()
if(this.socket.connected) {
try {
this.socket.emit('audio', {
id: this.id,
seq,
mimeType: this.mimeType,
data
})
} catch (e) {
console.error('caught an error', e)
this.stopRecording()
}
}
},
sampleRate: 44100,
desiredSampleRate: 44100,
numberOfAudioChannels: 1
})
}
}
On the server side (Express.js), I send the data as it's received to any interested clients. Here's the relevant code:
app.get('/play', (req, res, next) => {
try {
let id = req.query.id
let mimeType
if(!recordings[id]) {
// ...
}
emitter // the EventEmitter that's handling this
.on(`audio ${id}`, data => {
if(!mimeType) {
mimeType = data.mimeType
res.writeHead(200, {'Content-Type': mimeType})
}
res.write(data.data)
})
.on(`close ${id}`, () => {
console.debug({type:'audio close', id})
res.end()
})
} catch (e) {
next(e)
}
})
The issue is that each chunk I get from the client appears to be a complete WAV file, and concatenating such files doesn't work. When trying to play such a file, you only hear the first chunk.
I've been searching for hours for information about how to concatenate the input files (or any other method that would result in a stream that can be listened to). It seems that there's very little information out there about this topic.
I've been looking in particular at ffmpeg, but despite its purported ability to concatenate files, it expects the files to all be given on the command line. I'm receiving streaming data, so I can't practically list filenames in advance; I would have to send multiple files in on stdin, but that doesn't work.
Can anyone point me in the right direction? I would think that concatenating audio files would be a common need, but I can't find any tools that are capable of doing it without knowing in advance all of the data to be processed. Or am I barking up the wrong tree here?

How to download dynamic files from google drive

noob question, I'm just getting started with Google Drive API v3. How can I download dynamic file from google drive when I only have fileId. file can be, image, pdf, or docs.
I tried searching but I couldn't found any reference or example related to this.
This what I have so far but it only download specific file extension.
downloadFile(req, res) {
const auth = new google.auth.JWT(
client_email,
null,
private_key,
SCOPES,
);
const { fileId } = req.params;
const drive = google.drive({ version: 'v3', auth});
var dest = fs.createWriteStream('./tmp/downloads/dummy.pdf')
drive.files.get({
fileId,
alt: 'media',
}, {
responseType: 'stream'
}).then((driveResponse) => {
driveResponse.data.on('end', () => {
console.log(`downloading fileID ${fileId}`);
})
.on('error', (err) => {
console.log(err);
})
.on('data', (d) => {
console.log(d);
})
.pipe(dest)
})
.catch((err) => {
console.log(err);
})
}
Is there way to download dynamic files from google drive?
I believe your goal as follows.
You want to download the files from Google Drive using the service account and the file ID.
The files include both Google Docs files and the files except for Google Docs files.
You want to achieve this using googleapis for Node.js.
Modification points:
Unfortunately, from it only download specific file extension., I cannot understand about the detail of your situation. But I guess that the reason of your issue might be due to downloading both Google Docs files and the files except for Google Docs files.
When Google Docs files are downloaded, the files are required to be downloaded using the method of "Files: export" in Drive API.
When the files except for Google Docs files are downloaded, the files are required to be downloaded using the method of "Files: get" in Drive API.
I thought that above situation might be the reason of your issue.
In order to download both Google Docs files and the files except for Google Docs files, I propose the following flow.
Check the mimeType of the file ID.
Download the file using each method by the mimeType.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
var dest = fs.createWriteStream('./tmp/downloads/dummy.pdf')
drive.files.get({
fileId,
alt: 'media',
}, {
responseType: 'stream'
}).then((driveResponse) => {
driveResponse.data.on('end', () => {
console.log(`downloading fileID ${fileId}`);
})
.on('error', (err) => {
console.log(err);
})
.on('data', (d) => {
console.log(d);
})
.pipe(dest)
})
.catch((err) => {
console.log(err);
})
To:
drive.files.get({ fileId, fields: "*" }, async (err, { data }) => {
if (err) {
console.log(err);
return;
}
let filename = data.name;
const mimeType = data.mimeType;
let res;
if (mimeType.includes("application/vnd.google-apps")) {
const convertMimeTypes = {
"application/vnd.google-apps.document": {
type:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
ext: ".docx",
},
"application/vnd.google-apps.spreadsheet": {
type:
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
ext: ".xlsx",
},
"application/vnd.google-apps.presentation": {
type:
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
ext: ".pptx",
},
};
filename += convertMimeTypes[mimeType].ext;
res = await drive.files.export(
{
fileId,
mimeType: convertMimeTypes[mimeType].type,
},
{ responseType: "stream" }
);
} else {
res = await drive.files.get(
{
fileId,
alt: "media",
},
{ responseType: "stream" }
);
}
const dest = fs.createWriteStream(filename);
res.data
.on("end", () => console.log("Done."))
.on("error", (err) => {
console.log(err);
return process.exit();
})
.pipe(dest);
});
Note:
In this modification, I prepared 3 types of Google Docs files at convertMimeTypes. When you want to download other mimeTypes, please modify convertMimeTypes. In this case, for example, Google Docs files are downloaded as Microsoft Docs files.
References:
Download files
Files: get
Files: export

Turning image into blob in React Native (Expo) and uploading to S3 bucket

I have a camera component which I clicks a picture. I store the clicked picture using expo's FileSystem in the local cacheDirectory. Looks some thing like this:
onPictureSaved = async photo => {
await FileSystem.moveAsync({
from: photo.uri,
to: `${FileSystem.cacheDirectory}test.jpg`
});}
My next step is to my next stop is converting the image in the local cacheDirectory into a blob and upload the image into S3 via the aws-sdk:
var params = {
Bucket: "my-bucket",
Key: 'test.jpg',
Body: blob
};
s3.upload(params, function(err, data) {
if (err) {
console.log(err);
} // an error occurred
else {
console.log(data);
} // successful response
}
However, any methods or modules I install in order to accomplish this tiny step in the process hasn't been working at all. I can't use RNFS, react-native-fetch-blob or any other modules that require linking thanks to the expo client. I don't want to detach expo just for one thing. Is there any other way to accomplish this?
Take a look at https://github.com/expo/image-upload-example/issues/3#issuecomment-387263080. The latest expo release supports blobs, so then you can do something like the following:
uploadToS3 = async (fileUri, s3Bucket, s3Key) => {
const response = await fetch(fileUri);
const blob = await response.blob();
return new Promise((resolve, reject) => {
const params = {
Bucket: s3Bucket,
Key: s3Key,
Body: blob,
};
s3.upload(params, function(err, data) {
if (err) {
console.log('Something went wrong');
console.log(err);
reject(err);
} else {
console.log('Successfully uploaded image');
resolve(data);
}
});
});
};
Hope this helps!

Do I need the IPFS daemon to upload files from a browser?

I'm working on this project using IPFS and I'm trying to create a website that allows users to upload files directly from their browser to IPFS. My goal was that the website would be a front-end website but whenever I add a file to IPFS and I check it's hash on https://gateway.ipfs.io/ipfs/hash-here nothing happens, which made me think that the files are probably not getting uploaded to IPFS because I'm not running it on my local machine. Is this correct?
const Buffer = require('safe-buffer').Buffer;
export default function uploadFiles(node, files) {
let reader = new FileReader();
reader.onloadend = () => {
let byteData = reader.result.split('base64,')[1];
let fileData = Buffer.from(byteData);
node.files.add(fileData, (err, res) => {
if (err) {
throw err
}
let hash = res[0].hash
console.log(hash); ///////prints a hash that isnt visible on
//gateway
node.files.cat(hash, (err, res) => {
if (err) {
throw err
}
let data = ''
res.on('data', (d) => {
data = data + d
})
res.on('end', () => {
// console.log(data);
// console.log(atob(data));
})
})
});
}
reader.readAsDataURL(files['0']);
};
Are you running a js-ipfs node in your browser? Did you get the chance to look at the examples in the examples folder in js-ipfs repo? Url here: https://github.com/ipfs/js-ipfs/tree/master/examples
If you add a file to your node and the node is on, the IPFS gateway node will be able to find the content from your browser node.

Categories