Search code examples
javascriptnode.jsfile-uploadslackslack-api

How to upload an image to Slack using node.js on Windows?


I'm trying to upload an image via Slack using node.js and the request package, but not having much luck. Either I receive invalid_array_arg or no_file_data errors from the API.

Here is my request:

    var options = { method: 'POST',
      url: 'https://slack.com/api/files.upload',
      headers: 
       { 'cache-control': 'no-cache',
         'content-type': 'application/x-www-form-urlencoded' },
      form: 
       { token: SLACK_TOKEN,
         channels: SLACK_CHANNEL,
         file: fs.createReadStream(filepath)
        } };

    request(options, function (error, response, body) {
      if (error) throw new Error(error);

      console.log(body);
    });

I had a look at a few relevant posts:

The only thing that worked was using the curl command directly, but using cygwin (CommandPrompt failed: curl: (1) Protocol https not supported or disabled in libcurl). The issue calling curl from node (using child_process) but that silently fails in Command Prompt and still returns no_file_data using cygwin (passing an absolute path to the file):

stdout: {"ok":false,"error":"no_file_data"}
stderr:   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   469  100    35  100   434    359   4461 --:--:-- --:--:-- --:--:--  6112

I'm using node v6.9.1 on Windows.

What am I missing ? How can I upload an image to slack via node.js on Windows ?


Solution

  • The Slack API error invalid_array_arg means that there is a problem with the format of the arguments passed to Slack. (see here)

    When using the file property for files.upload, Slack excepts the data as multipart/form-data, not as application/x-www-form-urlencoded. So instead of form, you need to use formData in your request object. I also removed the incorrect part in the header.

    This works:

          var fs = require('fs');
          var request = require('request');
    
          var SLACK_TOKEN = "xoxp-xxx";
          var SLACK_CHANNEL = "general";
          var filepath = "file.txt";
    
          var options = { method: 'POST',
          url: 'https://slack.com/api/files.upload',
          headers: 
           { 'cache-control': 'no-cache' },
          formData: 
           { token: SLACK_TOKEN,
             channels: SLACK_CHANNEL,
             file: fs.createReadStream(filepath)
            } };
    
        request(options, function (error, response, body) {
          if (error) throw new Error(error);
    
          console.log(body);
        });