Meteor JS and TinyPNG API to compress uploaded PNG - node.js

I'm trying to recompress a PNG after upload and crop using tinyPNG API https://tinypng.com/developers/reference
My HTTP request in the server method looks like :
var tinyResponse = HTTP.post('https://api.tinypng.com/shrink', {auth: 'api:<myAPIkey>', data: image});
Where image is the base64 data like : data:image/png;base64,iVBORw0KG...
The api then tels me : "Does not appear to be a PNG file"
So I guess the TinyPNG API doesn't like the base64 format. What I should do is store the base64 into a temp file, use the API to compress, get the file back and re-encode it in base64. Yes what I want is to store the image file in the mongodb directly.
But my knowledge of node.js and Meteor is not suffisant for the moment.
Can someone throw me a bone here ? Thx
(Maybe I'm totally wrong and should use GM and cfs packages)

It would be nice if you provided more code or even your github repo but check the documentation for node: https://tinypng.com/developers/reference#node-js
You can use NPM packages with Meteor: http://docs.meteor.com/#/full/Npm-depends

Related

How can I upload image to s3 with Multer buffer?

I'm using the Multer library to upload an image. So, I use ReactJS to upload the file to the NodeJS server. In the NodeJS server, I received a piece of image information sent from the client as this picture.
In the s3 upload function, I use the buffer value in this picture as a body. I uploaded it to s3 successfully but when I open the image URL, it shows me like this picture.
There's any suggestion or correct way to upload an image to S3.
I would suggest you to use base64 encoding, 7bit enconding won't work for images as you are trying to do.
You can read more about that in this StackOverflow answer: https://stackoverflow.com/a/28531705/6334411

Is it more efficient for severs to send an image file or a path to an image file to the client?

I'm using express js to serve files to an angular app and I'm deciding between these approaches:
res.status(201).json({ imagepath: '<URL>' });
res.sendFile('<URL>');
I'm thinking that sending the url will force an extra round trip so I should go with the sendFile but I want to doublecheck. Is there anything I'm missing?
The best option would be to store the image file on something like AWS S3 and then send the file URL using your Express application. You would use the aws-sdk package here to save the image to S3 (detailed article here). Then you would send the URL location of that image to your database to be stored.

Node js upload file and resize after or before

I use express and multer for upload file(only image);but i want to resize image before or after.I searched a lot of;and i found a lot of documents.for example multer-imager(it wants amazon s3).I only want to uploiad file into my disk.I tried resize image before upload with canvas on clientside;but multer see unmodified image(i use multer limiter( 1mb ) ) and i get error: the file is bigger than 1mb.Because multer see unmodified image.
I had a same issue in my Ionic 3 mobile application. You can use croppr.js to crop the image before send to the server side. check this question
You can use multer-transform package

How to transfer base64 image from client to server or download binary / base64 from s3 bucket?

In my app, i'm sending photos directly from the client to s3, using something similar to this suggested heroku recommendation: https://devcenter.heroku.com/articles/s3-upload-node
The main benefit is that it saves server cost (i'm assuming since chunks aren't being sent to the server using something such as multipart-y form data).
However, I wish to be able to share these images to twitter also, which states this requirement:
Ensure the POST is a multipart/form-data request. Either upload the raw binary (media parameter) of the file, or its base64-encoded contents (media_data parameter). Use raw binary when possible, because base64 encoding results in larger file sizes
I've tried sending the base64 needed for the client-side s3 upload back to the server, but depending on the photo size -- I often get an error that it's too big to send back.
TLDR
Do I need to send my photos using mulitparty / multipart form data to my server, so I can have the needed base64 / binary to share a photo to twitter, or can I keep sending photos from my client to s3?
Then, somehow, efficiently obtain the needed base64 / binary on the server (possibly using the request module), so I can then send the image to twitter?
One fairly easy way to do this without changing your client code a whole lot would be to use S3 events. S3 events can trigger a lambda function in AWS that can post the image to twitter. You can use any library inside the lambda function to do efficient posting to twitter. Not sure if you want to use Lambda or stick to Heroku.
If you are directly uploading documents from the client to upload to s3, you are exposing your AWS secret/private keys with the client. A more secure way would be uploading the images to node and node in turn upload it to S3. A recommended way to upload images to node server would be using
multipart/form-data and using Multer middleware.
Regardless of the upload method, you can use the following code to serve images to twitter. This code uses AWS-SDK module.
var s3 = new AWS.S3();
var filename = req.query.filename;
var params = {
Bucket: <bucketname>,
Key: <image path>
};
var extension = filename.split('.')[1];
if (extension == "jpg" || extension == "JPG" || extension == "jpeg" || extension == "JPEG")
{
res.setHeader('Content-Type', 'image');
}
else if (extension == "png" || extension == "PNG")
{
res.setHeader('Content-Type', 'image/png');
}
s3.getObject(params).createReadStream().pipe(res);
This method can scale with easy like any other express app.

Image uploading - How to get the right format of image data for server side processing

I'm using sharp to process images on the server side and react dropzone to get the image file. When I post the file to the server from dropzone, I get the blob out of the request.body that looks like:
{ preview: 'blob:http%3A//127.0.0.1%3A3000/1451580a-b24f-478f-a9f7-338c0d790829' }
Optionally, before I send data to the server I can use FileReader (or something else) to do something with the image file instead of turning it into a blob.
Sharp takes:
A Buffer containing JPEG, PNG, WebP, GIF, SVG, TIFF
Raw pixel image data
A String containing the path to an image file, with most major formats supported.
How can I use what I have to provide sharp a supported format?
I recommend trying out a node.js module called Multer to help you access your photo file on your server.
https://github.com/expressjs/multer
First, on the client, you'll want to append your file to a FormData object like this:
// obtain the file from your react dropzone and save it to this file variable
const file = dropzone.file // not sure how you do this with react dropzone
const data = new FormData()
data.append('photo', file)
Then you'll send this FormData object to your server. On the server you'll use Multer on the route you're using for the photo for processing.
Make sure you npm install multer, and require it on your server or routes file. If you're sending a single file you'll use the multer 'single' method. If you want to do anything different check out the API documentation.
app.post('/photos', multer().single('photo'), controller.processPhoto);
In this example route, you're sending a POST request to /photos, multer is looking for a file with a FormData key of 'photo' and appending that to the request object.
Then in this made up 'controller.processPhoto' method you'll have access to the image as a property of the request object, on req.file. With this you can easily access a lot of good information including the image buffer req.file.buffer which it sounds like you need. (also mimetype, original name etc.)
This should be enough to get you started.

Resources