Search code examples
node.jsbase64slack-api

Posting a Base64-encoded image file to Slack channel from slackbot


At this point in my code, I've got an img variable which contains a base-64-encoded image. I've confirmed that the base-64 image is correct by logging img and pasting the output into the code beautify base-64 image encoder.

Now, I'm trying to figure out how to POST to the Slack API. I've read the files.upload method API documentation for Slack, which says they accept multipart form data or application/x-www-form-urlencoded, but I don't know how to convert from Base-64 to either of those from node.js. Once I've done the conversion, I also don't know how to make the actual post using request.post, as it's unclear to me how to encode the relevant information for the slack request.

Currently, I'm trying something like this:

        request.post({ url: 'https://slack.com/api/files.upload',
          formData: {
            token: slackToken,
            tile: "Image",
            filename: "image.png",
            filetype: "auto",
            channels: "testing",
            file: img,
          },
        }, function (err, response) {
            // just for debugging
            console.log(JSON.parse(response.body));
        });

Getting response: { ok: false, error: 'no_file_data' }, which makes sense, as Slack does not accept base-64 encoding of img

Any help much appreciated!


Solution

  • First, we'll need to trim the base64 encoding if it starts with: data:image/png;base64,

    Now the file system can help us with converting to a file with writeFileSync, which accepts a base64 encoding of a file and writes a file to the system. I'd like to find a way to do this without the side effect of writing a file to the system, but wasn't able to yet.

    Once that's ready, we can make our slack post request with the path to the newly created file as the file parameter. Working code below:

    let imgAsBase64 = img.substring(img.indexOf(',') + 1);
    
    require('fs').writeFileSync('image.png', imgAsBase64, 'base64', (err) => {
      console.log(err);
    });
    
    await request.post(
      {
        url: 'https://slack.com/api/files.upload',
        formData: {
          token: slackToken,
          tile: 'Image',
          filename: 'image.png',
          filetype: 'auto',
          channels: msg.channel,
          file: require('fs').createReadStream('./image.png')
        }
      },
      function (err, response) {
        // just for debugging
        console.log(response.body);
      }
    );