dannyk dannyk - 5 months ago 133
Node.js Question

Slack API (files.upload) using NodeJS

EDITED

I'm trying to structure the files.upload() API provided via Slack but am having a hard time understanding the correct format. At the moment, I am able to use the API to upload a text file but cannot for the life of me figure out how to upload an image.

Here's my issue: I have an image on my development server, let's call it image.png. I want to use the files.upload() API to post that image into a #general Slack channel. Below is the code I have that is successfully generating the image, but currently is just sending the text:

var myBarChart = new Chart(ctx).Bar(barChartData, barChartOptions);
var myBarChartDataURL = leaderboardBarChart.toBase64Image();

canvas.toBuffer(function(err, buf) {
if (err) throw err;
fs.writeFile(__dirname + "/leaderboard.png", buf);
});

bot.api.files.upload({
token: process.env.token,
title: "Image",
filename: "image.png",
filetype: "auto",
//content: "Posted with files.upload API",
file: fs.createReadStream("path/to/image_file.png"),
channels: filtered[0].id
}, function(err, response) {
if (err) {
console.log("Error (files.upload) " + err);
} else {
console.log("Success (files.upload) " + response);
};
});


When I run the code I get one of the following error:

"invalid_array_arg" which Slack details as: "The method was passed a PHP-style array argument (e.g. with a name like foo[7]). These are never valid with the Slack API."

I'm not entirely sure what to make of this error as I'm not using PHP nor anything that I can identify that would be PHP-like.

I've experimented with several different approaches for including the file path, whether using the 'fs' module, storing it in a variable, or just referencing it's absolute path (and even a relative path). I'm a bit lost and am just looking for some guidance.

I understand that this particular API uses multipart/form-data but I don't have a form. This app is strictly a NodeJS app. There is no framework (like Express) working in tandem with the main node script.

Any and all help is really appreciated. Again, just looking for some insight/guidance on what I'm missing or doing wrong.

Thanks in advance!

Answer

It looks like you'll have to go outside of Botkit's API here, since Botkit doesn't seem to support sending multipart/form-data.

Give this a try, using request directly (already in use by Botkit itself):

var request = require('request');

...

request.post({
    url: 'https://slack.com/api/files.upload',
    formData: {
        token: bot.config.token,
        title: "Image",
        filename: "image.png",
        filetype: "auto",
        channels: filtered[0].id,
        file: fs.createReadStream('test.png'),
    },
}, function (err, response) {
    console.log(JSON.parse(response.body));
});