tinify / tinify-nodejs

Node.js client for the Tinify API.
https://tinypng.com/developers
MIT License
414 stars 74 forks source link

Decode error with a buffer in base64 #17

Closed nicolasadamini closed 6 years ago

nicolasadamini commented 6 years ago

Hello!

I've been trying to tinify a picture coming from the file API. While this works:

var fs = require("fs");
fs.readFile("unoptimized.jpg", function(err, sourceData) {
  if (err) throw err;
  tinify.fromBuffer(sourceData).toBuffer(function(err, resultData) {
    if (err) throw err;
    // ...
  });
});

The following doesn't and I can't wrap my head around:

Server side

// ...Getting the response
const buf = Buffer.from(req.body.file, 'base64');
  tinify.fromBuffer(buf).toBuffer(function(err, resultData) {
    if (err) throw err;
      // ... throw Image could not be decoded (HTTP 400/Decode error)
    });

Client side

 // ... Getting a file from an input
  const reader = new FileReader();
  const fileName = photo[0].name;

  reader.readAsDataURL(photo[0]);
  reader.onload = (() => ({ target }) => uploadToS3(target.result))();

  const uploadToS3 = file => {
    const base64result = file.split(',')[1];
    const request = {
      method: 'post',
      url: 'http://localhost:5000/abc',
      data: `name=${fileName}&file=${base64result}`
    };
    axios(request)
      .then(function(response) {
        console.log(response);
      })
      .catch(function(error) {
        console.log(error);
      });
  };

Full log

node_modules/promise-nodeify/index.js:35
    later(() => { throw err; });
                  ^

Error: Image could not be decoded (HTTP 400/Decode error)
    at new ClientError (../node_modules/tinify/lib/tinify/Error.js:36:1)
    at Function.create (../node_modules/tinify/lib/tinify/Error.js:31:12)
    at IncomingMessage.response.on (../node_modules/tinify/lib/tinify/Client.js:89:35)
    at emitNone (events.js:111:20)
    at IncomingMessage.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1064:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickDomainCallback (internal/process/next_tick.js:218:9)

Using the aws-sdk the same 'buf' is working well so I don't know what to think...

mattijsvandruenen commented 6 years ago

Hi Nicolas,

The error that you're getting is caused by not providing proper binary image data to the Tinify library.

In your case, probably something is going wrong posting the base64 encoded image data to the server. For example, a base64 encoded string can include spaces, which need to be properly url encoded/decoded when you're not using standard multipart/form-data and processing/posting it yourself with custom code. The code that you're using to convert the base64 encoded image data to binary data on the server is certainly correct.

Some examples to illustrate that compressing images with a buffer works:

When I convert an image that is base64 encoded to binary and then compress it, it works fine: https://gist.github.com/warflower/f320e53ac2362f7012a733538460ac4e This gist includes a simple 2x1 pixels image with two colors represented in base64 encoding.

I've also made a very basic example with file upload from a form and a nodejs server: https://gist.github.com/warflower/cfdb376e25d2d2a2eeea332156c99c09

I hope that helps you on your way!

nicolasadamini commented 6 years ago

Indeed thanks a lot ! I was using the wrong encoding type