I am writing a simple wrapper in node.js which calls Goole Places API and gets a photo using photo_reference. When I run this and process the request from Postman it works but does not display photo itself. In the code below mapsClient.placesPhoto does return a huge response with many tags. Its not just raw image data. My question is how do I extract image or image data from googleResp object and send it back to client?
var googleMapsClient = require('#google/maps').createClient({
key: 'xyz'
});
app.post('/getGooglePlacePhoto/:photoref', function(req, res){
googleMapsClient.placesPhoto({
photoreference: req.params["photoref"],
maxwidth: 70,
maxheight: 70
}, function(err, googleResp){
if (!err) {
debug('got response from google');
res.set('Content-Type','image/jpeg');
debug(googleResp.body);
res.send(200, googleResp.body);
} else {
debug(err);
res.send(409, err);
return;
}
});
});
Related
Is it possible to post an image on twitter using nodejs and puppeteer? It find it hard because when you click on the image button on twitter it opens your archive.
It's definetely possible to post image on Twitter automatically (using Node.js). Twitter API Client for node called 'twit' suits for it. You can find the package on github or npm.
// post a tweet with media
var b64content = fs.readFileSync('/path/to/img', { encoding: 'base64' })
// first we must post the media to Twitter
T.post('media/upload', { media_data: b64content }, function (err, data, response) {
// now we can assign alt text to the media, for use by screen readers and
// other text-based presentations and interpreters
var mediaIdStr = data.media_id_string
var altText = "Small flowers in a planter on a sunny balcony, blossoming."
var meta_params = { media_id: mediaIdStr, alt_text: { text: altText } }
T.post('media/metadata/create', meta_params, function (err, data, response) {
if (!err) {
// now we can reference the media and post a tweet (media will attach to the tweet)
var params = { status: 'loving life #nofilter', media_ids: [mediaIdStr] }
T.post('statuses/update', params, function (err, data, response) {
console.log(data)
})
}
})
})
// post media via the chunked media upload API.
// You can then use POST statuses/update to post a tweet with the media attached as in the example above using `media_id_string`.
// Note: You can also do this yourself manually using T.post() calls if you want more fine-grained
// control over the streaming. Example: https://github.com/ttezel/twit/blob/master/tests/rest_chunked_upload.js#L20
//
var filePath = '/absolute/path/to/file.mp4'
T.postMediaChunked({ file_path: filePath }, function (err, data, response) {
console.log(data)
})
Okay, I see a few versions of this question out here, but I think mine goes a bit deeper than some of the others and I don't see satisfactory answers.
What I Want:
I have a page on a website that will have its contents frequently changed by users, and I want them to hit a button that says 'Generate PDF', and be able to turn the relevant information on the page into a nice looking PDF report.
I'm trying to do this with NodeJS, Express, with a deployment on Heroku.
Generically, this is how I'm trying to accomplish this:
MY PLAN:
Initiate a GET Request
Query a database for relevant results
Load data into an EJS template
Save the resulting HTML
Use the npm module HTML-pdf to stream it into the browser
Other important details:
This file is meant to be ephemeral. I don't want to save it
anywhere.
I prefer not to even have to write it anywhere, since it's only
meant to exist in the browser at that moment.
This app is deployed on Heroku, and need to work within its
constructs. I prefer not to use a file store like S3.
MY CODE:
router.get('/formulas/:id/pdf', function(req, res){
var db = req.db.collection('users');
var id = new ObjectID(req.params.id);
var pointer = {"formulas.$": 1, "_id": 0};
//query database, get the info out
db.aggregate([
{$match: {"formulas.f_id": id}},
{$unwind: "$formulas"},
{$match: {"formulas.f_id": id}},
{$project : {"formulas": 1, "_id": 0}}
]).toArray(function(e, doc){
if (e) {
throw e;
} else {
var html = null;
ejs.renderFile('./views/pdf.ejs', { //create template from db query
project: doc[0].formulas,
title: 'Formula Info Report',
description: 'PDF Report For Your Formula by Nutraceutical Pro',
ID: 'pdf',
keywords: 'PDF, PDF generator, Formula Info Report',
user: req.user,
loggedIn: req.isAuthenticated()
}, function(err, results){
if (err) {
console.log(err);
}
html = results; //save results of HTML output
});
var options = { format: 'Letter' };
var path = './public/pdf/formula-' + req.params.id + '.pdf';
pdf.create(html, options).toStream(function(err, stream) {//initiate stream
if (err) {
return console.log(err);
}
if (stream) {
console.log(stream);
stream.pipe(fs.createWriteStream(path));
console.log("the pdf was streamed.");
res.end();
}
});
}
});
});
I initiate the GET request with an AJAX call like so:
$('.getPDF').click(function(){
var filepath = 'https://my-domain.herokuapp.com/pdf/formula-' + this.id + '.pdf';
$.ajax({
url: '/formulas/'+ this.id +'/pdf',
type: 'GET',
success: function () {window.open(filepath);}
});
When I run the script I generate a stream, and the console logs that the PDF was created. If I just save the resulting file to my local system it comes out fine, but in my app I get the following error message:
Cannot GET /pdf/formula-59cc38992fb99b00045832ad.pdf
So it's like the raw material for the PDF is being created, but it's not being logged and created in such a way that allows the app to read it.
I'm open to a variety of solutions for this, so if there are much easier ways to do it I'm all ears. Prefer to stick with my current stack though.
I am creating a application using mean stack, in which i am using angular 2 for the client side. I had created a form that contain some input fields and a image. Now, for submitting the form i am using formdata to send data to the node server. now I am unable to show, access and save the data at the node server. Please somebody help me as I am new to mean stack.
data array:
const newProduct = {
category: this.pcategory,
name: this.name,
description: this.description,
price: this.price,
quantity: this.quantity,
image: this.fileName
}
here is the code for sending data:
imagedata contain the data of the file
addProduct(newProduct, imagedata:File) {
let formData: FormData = new FormData();
formData.append('body', JSON.stringify(newProduct));
formData.append('file', image, newProduct.imagedata);
let headers = new Headers();
headers.append("enctype", "multipart/form-data");
headers.append("Accept", "application/json");
let options = new RequestOptions({ headers: headers });
return this.http.post('http://localhost:3000/product/add' ,formData, options).map((response: Response) => response.json());
}
here is the code for receiving and saving data:
function (req, res) {
var storage = multer.diskStorage({//multers disk storage settings
destination: function (req, file, callback) {
callback(null, './uploads');
}
});
var upload = multer({//multer settings
storage: storage
}).any();
var model = new Model(req.body);
model.save(function (err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.status(201).json(model);
}
});
upload(req, res, function (err) {
if (err) {
// An error occurred when uploading
console.log(err);
return res.status(422).send("an Error occured")
}
});
}
In angular 2 you cannot upload image with this approach consider using this Angular 2 module ng2-file-uploader. You can see the demo app here Angular File Uploads with an Express Backend
.
One solution could be to convert your image to base64 string and pass that string in your model. And then have that base64 string convert back to image in the server.
I am using Twitter module for nodejs to upload media to my twitter account. As example program from here https://github.com/desmondmorris/node-twitter/tree/master/examples#media.
Instead of using image from system i am passing a base64 encoded string of the image. When i run this program it output the base64 string(image) in the console in a loop and after a while it crashes and doesn't upload my image.
// Load your image
var data = require('fs').readFileSync(image);
// Make post request on media endpoint. Pass file data as media parameter
client.post('media/upload', {media: image}, function(error, media, response){
if (!error) {
// If successful, a media object will be returned.
console.log(media);
// Lets tweet it
var status = {
status: 'I am a tweet',
media_ids: media.media_id_string // Pass the media id string
}
client.post('statuses/update', status, function(error, tweet, response){
if (!error) {
console.log(tweet);
}
});
}
else{
console.log("error upload");
}
});
So i tried different method. I saved the base64 encode image in to out.png
fs.writeFile("out.png", data.image, 'base64', function (err) {
console.log(err);
});
var data = require('fs').readFileSync("out.png");
and this code output error saying
Error: ENOENT: no such file or directory, open 'D:\Local server\nodejs\out.png'
This file does exist i have confirmed
Update
Api returns [Error: Status Code: 400]
hi there are several nodejs api which allows to serve as a client library for Twitter, and with which you can upload your media to your twitter account, the most popular twitter and are node-twitter-api
i try to readout an image, saved in mongodb, via gridfs (without temporary file)
it should be directly sent to ajax, which injects it into html
when i use my actual functions a large bit string is formed and sent to client (is saved in ajax response var)
but as it reaches the client, the bits arent correct anymore
so i look for a way to encode the picture before it is sent (into base64)
(or is there any other way?)
Serverside - javascript, gridfs
exports.readFileFromDB = function(req, res, profile, filename, callback){
console.log('Find data from Profile ' + JSON.stringify(profile));
var GridReader = new GridStore(db, filename,"r");
GridReader.open(function(err, gs) {
var streamFile = gs.stream(true);
streamFile.on("end", function(){
});
// Pipe out the data
streamFile.pipe(res);
GridReader.close(function(err, result) {
});
Clientside - javascript ajax call:
function imgUpload(){
var thumb = $("#previewPic");
$('#uploadForm').ajaxSubmit({
beforeSend:function(){
//launchpreloader();
},
error: function(xhr) {
//status('Error: ' + xhr.status);
},
success: function(response) {
console.log(response);
var imageData = $.base64Encode(response);
console.log(imageData);
thumb.attr("src","data:image/png;base64"+imageData);
$("#spanFileName").html("File Uploaded")
}
});
}
I'm doing something similar for a current project, but when the upload is complete, I return a JSON object containing the URL for the uploaded image:
{ success : true, url : '/uploads/GRIDFSID/filename.ext' }
I have a route in Express that handles the /uploads route to retrieve the file from GridFS and stream it back to the client, so I can use the above URL in an IMG SRC. This is effectively what appears in the DOM:
<img src="/uploads/GRIDFSID/filename.ext">
The route handler looks something like this (it uses node-mime and gridfs-stream):
app.get(/^\/uploads\/([a-f0-9]+)\/(.*)$/, function(req, res) {
var id = req.params[0];
var filename = req.params[1];
// Set correct content type.
res.set('Content-type', mime.lookup(filename));
// Find GridFS file by id and pipe it to the response stream.
gridfs
.createReadStream({ _id : id })
.on('error', function(err) {
res.send(404); // or 500
})
.pipe(res);
});
It obviously depends on your exact setup if my solution works for you.