file streaming to object store through ibm-cos-sdk - ibm-cloud

I have seen the sample code in the site https://www.npmjs.com/package/ibm-cos-sdk :
function doCreateObject() {
console.log('Creating object');
return cos.putObject({
Bucket: 'my-bucket',
Key: 'foo',
Body: 'bar'
}).promise();
}
Is it possible to supply stream as a body (e.g. file being uploaded) instead of supplying the entire body as once?

Try:
var stream = fs.createReadStream('/Users/paulcarron/Desktop/image.jpeg');
function doCreateObject() {
console.log('Creating object');
return cos.putObject({
Bucket: bucket,
Key: 'foo.jpg',
Body: stream
}).promise();
}

Related

Single value in ionic http post param

Hi I'm new to ionic/angular and I'm reading someone else code and came across the function below in the Service
makePostRequest(100)
public makePostRequest(param) {
return this.http.post('/sample/api', param);
}
Does this mean param is sent as json body or just a value, online documentation just shows json body as the argument not a single value. Can someone help me with this
Thanks in advance.
The post body is sent as serialized parameters as explained here.
In the example you have provided, they are calling the makePostRequest() function and providing an argument of 100. When the makePostRequest() function runs, it takes that value from the argument and sets it as a parameter which is then used to populate the body in the POST request.
You can still send single values as you would multiple values with something similar to this:
sendData() {
const data = {
number: 100
};
return this.http.post('myurl.com', data);
}
Or for multiple:
sendData() {
const data = {
number: 100,
fruit: 'banana'
};
return this.http.post('myurl.com', data);
}
You can of course pass multiple arguments if you have parameters set up to accept them:
sendData(body: { score: number, fruit: string }) {
return this.http.post('myurl.com', body);
}

Flutter Cloud Messaging: how to send notification from the app (not from firebase console)

Is it possible to send the notification from within the app instead of a cloud function on firebase?
The reason is, I want to do something similar to: FCM Push Notifications for Flutter, where they have this function that will be deployed to firebase:
export const sendToTopic = functions.firestore
.document('puppies/{puppyId}')
.onCreate(async snapshot => {
const puppy = snapshot.data();
const payload: admin.messaging.MessagingPayload = {
notification: {
title: 'New Puppy!',
body: `${puppy.name} is ready for adoption`,
icon: 'your-icon-url',
click_action: 'FLUTTER_NOTIFICATION_CLICK' // required only for onResume or onLaunch callbacks
}
};
return fcm.sendToTopic('puppies', payload);
});
this method works as intended on firebase cloud functions, however I need the path
.document('puppies/{puppyId}')
to be dynamic depending on which chatroom a user is in, so he would get a notification everytime i new message is send, so the 'chatroom22' would be a variable:
.document('chatroom22/{roomId}')
So is it possible to do this in the app-code, or can this be done in the deployed function?
In response to Doug Stevensons answer
Okay, that makes sence, and works. However, now everybody get the notifications. I want only the people in a given chatroom to receive the notification. I've tried something like this, where the users device token is saved for a given chat-room, then I want to notiffy all those tokens:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().functions);
var newData;
exports.myTrigger = functions.firestore.document('messages/{messageId}/room/{roomId}/message/{messageId2}').onCreate(async (snapshot, context) => {
//
if (snapshot.empty) {
console.log('No Devices');
return;
}
newData = snapshot.data();
const deviceIdTokens = await admin
.firestore()
.collection('messages/{messageId}/room/{roomId}/tokens/{tokenId}')
.get();
var tokens = [];
for (var token of deviceIdTokens.docs) {
tokens.push(token.data().device_token);
}
var payload = {
notification: {
title: `${newData.sender}`,
body: `${newData.message}`,
sound: 'default',
},
data: {
push_key: 'Push Key Value',
key1: newData.message,
},
};
try {
const response = await admin.messaging().sendToDevice(tokens, payload);
console.log('Notification sent successfully');
} catch (err) {
console.log(err);
}
});
But it doesnt seem to work with wildcards.. how can I get the specific destination for each chatroom?
You can use a wildcard for the collection in the path:
functions.firestore.document('{collectionId}/{documentId}')
But this will trigger for all documents in all top-level collecitons, which is probably not what you want.
In fact, using variable names for top-level collections is actually not the preferred way to model data in Firestore. Consider instead having a top-level collection for all rooms, then use subcollections to contain their messages. If you do that, then you function becomes more more clearly defined as:
functions.firestore.document('rooms/{roomId}/messages/{messageId}')
Cloud Fuctions only allows wildcards for full path segments like this. There are no other patterns or regular expressions.

AWS Lambda return a file

I'm reading a CSV file from S3 using Lambda and want to return that file to the caller of the lambda function. I don't want to print the file through outputstream - I want to return the actual file. Is there a way to do this? I get the S3 file like this:
override def handleRequest(inputStream: InputStream,
outputStream: OutputStream,
context: Context): Unit = {
...
val s3File = s3Client.getObject(bucketName, bucketKey)
}
How can I return the actual file (as opposed to converting it to String and printing via outputStream)?
The above can be done using nodejs aws lambda with express server. You could use aws provided package
// lambda.js
'use strict'
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app')
const server = awsServerlessExpress.createServer(app)
exports.handler = (event, context) => { awsServerlessExpress.proxy(server, event, context) }
// app.js
// refer the examples for complete code
// https://github.com/awslabs/aws-serverless-express/blob/master/examples/basic-starter/app.js
...
router.get('/download', (req, res) => {
s3.getObject({Bucket: myBucket, Key: myFile},function(err,data){
if (err) {
// report error and return the server error
return res.status(500).send("Error!");
}
// set the http Headers
res.set("Content-Length",data.ContentLength)
.set("Content-Type",data.ContentType);
// send the data
res.send(data.Body);
});
});
...
PS: I have not tested the above code.

Pg-promise - How to stream binary data directly to response

Forgive me I'm still learning. I'm trying to download some mp3 files that I have stored in a table. I can download files directly from the file system like this:
if (fs.existsSync(filename)) {
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-Type', 'application/audio/mpeg3');
var rstream = fs.createReadStream(filename);
rstream.pipe(res);
I have stored the data in the table using pg-promise example in the docs like so:
const rs = fs.createReadStream(filename);
function receiver(_, data) {
function source(index) {
if (index < data.length) {
return data[index];
}
}
function dest(index, data) {
return this.none('INSERT INTO test_bin (utterance) VALUES($1)', data);
}
return this.sequence(source, {dest});
} // end receiver func
rep.tx(t => {
return streamRead.call(t, rs, receiver);
})
.then(data => {
console.log('DATA:', data);
})
.catch(error => {
console.log('ERROR: ', error);
});
But now I want to take that data out of the table and download it to the client. The example in the docs of taking data out of binary converts it to JSON and then prints it to the console like this:
db.stream(qs, s => {
s.pipe(JSONStream.stringify()).pipe(process.stdout)
})
and that works. So the data is coming out of the database ok. But I can't seem to send it to the client. It seems that the data is already a stream so I have tried:
db.stream(qs, s => {
s.pipe(res);
});
But I get a typeerror: First argument must be a string or Buffer
Alternatively, I could take that stream and write it to the file system, and then serve it as in the top step above, but that seems like a workaround. I wish there was an example of how to save to a file in the docs.
What step am I missing?

HTTP Request PUT file (image) to Swift RESTful API (Grails)

// authenticate
def authSite = new HTTPBuilder( 'https://*********.objectstore.eu/' )
authSite.auth.basic '******', '******'
def filestore = new File("C:/*****")
filestore.createNewFile()
FileUtils.writeStringToFile(filestore, "datawhathwat")
//save object
authSite.request(PUT) { req ->
uri.path = '/images/********.txt'
headers.'Content-Type' = 'image/jpg'
body: "filestore"
}
authSite.shutdown()
When using this code, the headers come through, a file is created, but the file is empty.
Here is a link to the API documentation: http://developer.openstack.org/api-ref-objectstorage-v1.html#createOrReplaceObject
In the request body you are passing a string, rather than the contents of the file you are trying to upload. Get the contents of the file into the body this way:
authSite.request(PUT) { req ->
...
body: filestore.bytes
}