Node-slack-sdk: Helper function to download a file

Created on 7 Jan 2017  路  6Comments  路  Source: slackapi/node-slack-sdk

I suggest adding a method on the Web API to download a file from slack, symmetrical to files.upload.

enhancement good first issue

Most helpful comment

i think the SDK could provide a helper function to download actual files. what i'm imagining is a function web.helpers.fileDownload(fileId, [opts]) and the opts could allow you to specify if you want the return value to be a readable stream or a Buffer.

All 6 comments

First off, this repository is for handling the client that _uses_ the Web API, which is produced by some lovely engineers at Slack. We have no control over what is and isn't in the API. Nonetheless, such a method (one that downloads files) isn't exactly possible with the Web API (can't _force_ a client to download something, you can only send data).

But, there is a way to do what you're looking for: simply use an http client (such as request) to go to the file's url (which you can get using the files.list method) and save the file's response to disk.

Further, there's a special little bit of authentication you need to do in your request to get the file (using it's url_private field), as specified by the file type documentation. Simply, there must be an Authorization header present in the request that's set to Bearer YOUR_TOKEN (which may be the bot's token or a OAuth token).

Here's an example of what all of that would look like:

const fs = require('fs');
const request = require('request');
const WebClient = require('@slack/client').WebClient;

const web = new WebClient(your token and options);

web.files.list({}, function(err, fileListResp) {
  if (err)
    return console.log(err);

  // Strategically choose a file to download.
  let filePrivateUrl = fileListResp.files[Math.floor(
    Math.random() * fileListResp.files.length)].url_private;

  // If you don't want to write the returned data to a file then just remove the
  // `pipe` call and supply `request` with a callback.
  request({
    url: filePrivateUrl,
    headers: {
      'Authorization': 'Bearer ' + YOUR_TOKEN // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    }
  }).pipe(fs.createWriteStream('./thefile'));
});

I didn't test the code, it could error. I'm also unaware of any situation in which a file doesn't have a url_private field. You'll have to do your own testing to make sure the above approach is sound (sorry). It should still be a solid basis for what you're attempting to achieve. Good luck!

Small correction: Authentication should be Authorization

Thanks for noticing that @eelkeh! I edited my response to help anyone else who looks at it in the future.

i think the SDK could provide a helper function to download actual files. what i'm imagining is a function web.helpers.fileDownload(fileId, [opts]) and the opts could allow you to specify if you want the return value to be a readable stream or a Buffer.

As a reminder, this is an issue where we'd be happy to review and accept a contribution from the community. If you need any guidance or help with that process, let us know.

Im trying to download a file using Python and have similar syntax, however when I download the file along with the Auth token as suggested above, I get the Slack html web page asking me to sign in.

tokenSlackAuth = "Bearer xoxp-"
headers={"Authorization": tokenSlackAuth, "content-type" : contentType}
filename = download_file(url, filePath, headers)

def download_file(url, filename, headers):
f = open(filename, "w")
try:
with requests.get(url, headers) as req:
with open(filename, 'wb') as f:
for chunk in req.iter_content(chunk_size=1024):
if chunk:
print("chunk : ", chunk)
f.write(chunk)
return filename
except Exception as e:
print(e)
return None

Was this page helpful?
0 / 5 - 0 ratings