Using Seneca

Remember that routing on this framework is all about patterns. Let's keep it simple for now and use a role property to indicate what we want to do (upload, check, or download).

By default, every message should be JSON-encoded, so we'll encode the image in base64 to pass it as a string inside the JSON messages to upload and download.

Create a folder for our Seneca service, and then create a child folder called uploads. Then, install seneca and sharp on that folder by running the following command:

npm install seneca sharp --save

Then, create a file called imagini.js with the following content:

const seneca  = require("seneca");
const sharp = require("sharp");
const path = require("path");
const fs = require("fs");
const service = seneca();

service.add("role:upload,image:*,data:*", function (msg, next) {
let filename = path.join(__dirname, "uploads", msg.image);
let data = Buffer.from(msg.data, "base64");

fs.writeFile(filename, data, (err) => {
if (err) return next(err);

return next(null, { size : data.length });
});
});

service.listen(3000);

What this does is initiate a simple service with a route for uploading. Since we're receiving all the image content directly on an object property, I used fs.writeFile. It's a simpler method and gives me an error whether something incorrect happens, which we can pass on to the route response.

I also used Buffer.from to convert our image data, which we'll be uploading in base64.

So, let's just start it as we did with the others. I included the same example.png image and used curl to test this out.

curl -H "Content-Type: application/json" 
--data '{"role":"upload","image":"example.png","data":"'"$( base64 example.png)"'"}'
http://localhost:3000/act

Seneca promptly replied with the following:

{"size":55543}

This is the image size. Notice I'm taking advantage of bash interpolation (variable substitution) to directly convert the image file to base64 and pass it to curl, which then sends that JSON piece of data to our service:

service.add("role:check,image:*", function (msg, next) {
let filename = path.join(__dirname, "uploads", msg.image);

fs.access(filename, fs.constants.R_OK , (err) => {
return next(null, { exists : !err });
});
});

Our check route is very similar. Instead of just replying with an HTTP 404 response code, we reply with a stringified JSON object with a boolean property exists, which will indicate if the image was found.

Here, we are checking for our image using curl:

curl -H "Content-Type: application/json" 
--data '{"role":"check","image":"example.png"}'
http://localhost:3000/act

We will respond with the following:

{"exists":true}

If you change the image name, it will respond with false:

service.add("role:download,image:*", function (msg, next) {
let filename = path.join(__dirname, "uploads", msg.image);

fs.access(filename, fs.constants.R_OK , (err) => {
if (err) return next(err);

let image = sharp(filename);
let width = +msg.width;
let height = +msg.height;
let blur = +msg.blur;
let sharpen = +msg.sharpen;
let greyscale = !!msg.greyscale;
let flip = !!msg.flip;
let flop = !!msg.flop;

if (width > 0 && height > 0) {
image.ignoreAspectRatio();
}

if (width > 0 || height > 0) {
image.resize(width || null, height || null);
}

if (flip) image.flip();
if (flop) image.flop();
if (blur > 0) image.blur(blur);
if (sharpen > 0) image.sharpen(sharpen);
if (greyscale) image.greyscale();

image.toBuffer().then((data) => {
return next(null, { data: data.toString("base64") });
});
});
});

Our downloaded route has some changes:

  • Instead of query parameters, we check directly on msg. One noticeable advantage is that we have types and not just strings, so we can use Boolean and numbers directly.
  • Instead of returning the image in binary, so that we could just open in the browser, we convert it to base64 and pass it on the JSON response.

We need some tools to test this on the command line. Since I use JSON a lot, I have jq installed. I strongly recommend you install it too and take a look at the tutorials. It will make your life easier. Using the base64 command we previously used to encode, we can decode the content and pipe the data to a local file:

We can then open the folder and see the image is there. Notice I added greyscale and resized the image just by passing two more JSON parameters:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset