Meteor FS.Collection access collection on server - node.js

I'm using FS.Collection to upload short video file on a server and then send it as an attachment in email.
Inserting to the collection on server works and I can access collection items on the client, also, stream it directly with a path to the file Url - localhost:3000/cfs/files/videos/{{item_id}}
I wonder how to access collection on the server. I want to send an email with attachment in the following form and need to access path to file and filename on the server. I tried doing:
Email.send({
to: to,
from: from,
subject: subject,
text: text,
attachments:[{fileName:"video.mp4", filePath:"/cfs/files/videos/{{item_id}}"}]
});
It displays the attachment video player in the email, but with an error message, so I assume I'm not accessing a file correctly.
My Collection.js is simple:
var videoStore = new FS.Store.GridFS("videos");
Videos = new FS.Collection("videos", {
stores: [videoStore]
});

You can not use attachment by filePath of collectionFS. "/cfs/files/videos/{{item_id}}" is a virtual path, i.e. files don't exist in /cfs/files/videos, neither there is folder '/cfs/files/videos'.
You can use http path instead:
var ROOT_URL = process.env.ROOT_URL;
var rootUrl;
if (ROOT_URL.indexOf('/', ROOT_URL.length - 1) != -1) {
rootUrl = ROOT_URL.substring(0, ROOT_URL.length - 1);
} else {
rootUrl = ROOT_URL;
}
var attachments = [];
attachment = {
fileName: fileName(url),
filePath: rootUrl + "/cfs/files/videos/{{item_id}}"
};
attachments.push(attachment);
Email.send({
to: to,
from: from,
subject: subject,
text: text,
attachments: attachments
});

Related

Google Drive API sending PDF attachments in emails

I have some node.js code that reads in a PDF file using Google Drive API drive.files.get()... (it's a file that is sourced on our Google team/shared drives). I convert the returned stream to a single base64 data chunk with something like this:
// read using drive.files.get() into 'pdfStream'
//...
let pdf64 = '';
pdfSream.on('readable', function () {
var chunk = pdfStream.read();
if (chunk != null) {
var chunk64 = chunk.toString('base64');
pdf64 += chunk64;
}
});
pdfStream.on('end', function () {
// Do SendGrid email with pdf64 as attachment
});
Note that the final goal is to send an email with the PDF. I haven't included much of the code because this all works great - as long as the email recipient is on our company's domain. For external email recipients, the PDF attachment is unviewable and cannot be downloaded - at least this is what the situation appears to be.
I didn't think that access-restrictions and permissions would stay with data that is read directly using drive.files.get(). Is this a thing? I would suspect SendGrid except that we send attachments in other areas of our code with no issue.
Thoughts anyone? Much appreciated!
~Bob
I was able to fix it. The permissions thing was a red herring - the pdf attachments were corrupt and our company email system was just more lenient with the errors than others (like Gmail). I refactored the above code to first create a complete array of data, then converted that array to base64:
// read using drive.files.get() into 'pdfStream'
//...
let pdfChunks = [];
// Read through stream chunks and concat them together
pdfStream.on('readable', function () {
var chunk = pdfStream.read();
if (chunk != null) {
pdfChunks.push(chunk);
}
});
// On the end of the stream, convert to base64 and email the Pdf
pdfStream.once('end', function () {
let pdfBin = Buffer.concat(pdfChunks);
let pdf64 = pdfBin.toString('base64');
//...
// Do SendGrid email with pdf64 as attachment
});
Cheers!
~Bob

How to read data from the downloaded excel file content from Google drive api in Dart/Flutter?

I am using google drive API to download an excel file in my Flutter app but I want to store the downloaded file content response in a File and then do some update operations using excel dart package, below is the given code from reading an xlsx file from a path location.
var file = "Path_to_pre_existing_Excel_File/excel_file.xlsx"; //here I want to store the response from drive api
var bytes = File(file).readAsBytesSync();
var excel = Excel.decodeBytes(bytes);
//Do some logic here
for (var table in excel.tables.keys) {
print(table); //sheet Name
print(excel.tables[table].maxCols);
print(excel.tables[table].maxRows);
for (var row in excel.tables[table].rows) {
print("$row");
}
}
//then saving the excel file
// updating the excel sheet to Drive
updateToDrive(excel,fileId);
I have created all the required auth functions, drive scopes and my download function looks like this :
Future<void> downloadFile() async{
String fileId = '1TOa4VKfZBHZe######WLA4M95nOWp';
final response = await driveApi.files.get(
fileId,
downloadOptions: drive.DownloadOptions.fullMedia
);
print(response);
}
This function is executing correctely and giving Media type response, but I could not able to read this response so that I could store it in a file.
Any help would be truly appreciated, Thanks
I changed my download function to this, as drive.files.get() was returning a Future Object so I changed it to return Future<Media?> by type casting.
String fileId = "19jF3lOVW563LU6m########jXVLNQ7poXY1Z";
drive.Media? response = (await driveApi.files.get(
fileId,
downloadOptions: drive.DownloadOptions.fullMedia
)) as drive.Media?;
Now response is a Media on which we can listen to the sream to store the response in a file.
To do that first we need to get the app directory by path_provider
final String path = (await getApplicationSupportDirectory()).path;
final String fileName = '$path/Output.xlsx';
File file = File(fileName);
Now we want to write the stream of response Stream<List> into our file object which I found from this link
List<int> dataStore = [];
await response!.stream.listen((data) {
print("DataReceived: ${data.length}");
dataStore.insertAll(dataStore.length, data);
}, onDone: () {
print("Task Done");
file.writeAsBytes(dataStore);
OpenFile.open(file.path);
print("File saved at ${file.path}");
}, onError: (error) {
print("Some Error");
});
Now we can do whatever we want to make changes through excel package.

how to send a mail in a particular format by using send grid

I am able to send a mail by using send grid API how to send a mail in particular format by using send grid
Mail-Format
please find the Mail-format image
Pass in the body as HTML and set the IsBodyHtml = true. I do this using SendGrid.
public Task SendEmailAsync(string email, string subject, string htmlMessage)
{
var client = new SmtpClient(host, port)
{
Credentials = new NetworkCredential(userName, password),
EnableSsl = false
};
return client.SendMailAsync(
new MailMessage(from, email, subject, htmlMessage) { IsBodyHtml = true }
);
}

NodeJS params.Example not being used by #sendgrid/mail

Watson Assistant passes my params.finalemail and params.guestemail correctly. It looks like your #sendgrid/mail is not accepting the values of these params. Why is that?
Basically, Watson passes the $guest email as the "to" email address and the $finalemail contain the main body of the email.
I need my function to send an email with the information contained in the above varibles.
const sgMail = require('#sendgrid/mail');
/* Replace YOUR-SENDGRID-API-KEY-GOES-HERE with
the API Key you get from SendGrid.
*/
sgMail.setApiKey('apikey')
function sendmail(params) {
params.guestemail
params.finalemail
let msg = {}
msg.to = params.guestemail
msg.from = 'example#outlook.com'
msg.subject = 'Your Reservation'
msg.html = params.finalemail
sgMail.send(msg,(error, json) => {
if (error) {
console.log(error)
}
})
return { sent: 1 }
}
Sendgrid will send either text field or html not both. To send the message that you want you can add 'This message is HTML only.' in an html tag.

Issue in attachment upload in BOT emulator of Bot framework

I am uploading an attachment in BOT emulator, after uploading an attachment I am converting it to base64, to pass it to our service.
I pick this attachment from path D:\Images\MobileRequest.PNG, but after uploading it to BOT app it shows the path of attachment as http://127.0.0.1:44185/v3/attachments/ne7djbemc9f40bifi/views/original/MobileRequest.PNG, as the image is not available on this path, So while converting the image to base64, it throws an error as "URI formats are not supported.".
How to get actual physical path i.e "D:\Images\MobileRequest.PNG" in BOT app.
Below is code from my BOT app
var dialog = new PromptDialog.PromptAttachment("Please attach screenshot ", "Sorry, I didn't get the attachment. Try again please.", 2);
context.Call(dialog, afterUpload);
private async Task afterUpload(IDialogContext context, IAwaitable<IEnumerable<Attachment>> result)
{
IEnumerable<Attachment> attach = await result;
string filePath = attach.FirstOrDefault().ContentUrl + "/" + attach.FirstOrDefault().Name;
context.UserData.SetValue("filePath", filePath);
}
string filePath = string.Empty;
context.UserData.TryGetValue("filePath", out filePath);
using (System.Drawing.Image image = System.Drawing.Image.FromFile(filePath))
{
using (MemoryStream m = new MemoryStream())
{
image.Save(m, image.RawFormat);
byte[] imageBytes = m.ToArray();
attach1 = Convert.ToBase64String(imageBytes);
}
}
Your bot will be deployed so you will not have access to local files.
You can easily convert your image located at a URL by doing the following:
using (var client = new HttpClient())
{
var bytes = await client.GetByteArrayAsync(imageUrl);
var imageInBase64String = "image/jpeg;base64," + Convert.ToBase64String(bytes);
// Do what you want with your converted image
}

Resources