Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix files.upload from Buffer with formData options #307

Closed
jsarafajr opened this issue Jan 3, 2017 · 5 comments · Fixed by #435
Closed

fix files.upload from Buffer with formData options #307

jsarafajr opened this issue Jan 3, 2017 · 5 comments · Fixed by #435
Labels
bug M-T: A confirmed bug report. Issues are confirmed when the reproduction steps are documented good first issue
Milestone

Comments

@jsarafajr
Copy link

Getting Error: no_file_data while uploading Buffer object with files.upload.

// doesn't work (see trace log below)
const image = fs.readFileSync('image.png');
await bot.files.upload('image.png', {
  file: image
});

// text buffer doesn't work too
await bot.files.upload('text.txt', {
  file: new Buffer('hello world');
});

// uploads image as Plain Text (incorrect)
await bot.files.upload('image.png', {
  content: image
});

// works well with streams
const imageStream = fs.createReadStream('image.png')
await bot.files.upload('image.png', {
  file: imageStream
});

Stacktrace:

2016-12-27T13:58:29.415Z - error:  Error: no_file_data
     at handleHttpResponse (/bot/node_modules/@slack/client/lib/clients/transports/call-transport.js:105:17)
     at handleTransportResponse (/bot/node_modules/@slack/client/lib/clients/transports/call-transport.js:155:19)
     at apply (/bot/node_modules/lodash/lodash.js:499:17)
     at wrapper (/bot/node_modules/lodash/lodash.js:5356:16)
     at Request.handleRequestTranportRes (/bot/node_modules/@slack/client/lib/clients/transports/request.js:20:5)
     at apply (/bot/node_modules/lodash/lodash.js:499:17)
     at Request.wrapper [as _callback] (/bot/node_modules/lodash/lodash.js:5356:16)
     at Request.self.callback (/bot/node_modules/request/request.js:186:22)
...
@linuxfreakus
Copy link

I too am interested in how to make this happen. I've tried wrapping the Buffer as a Readable stream... no dice. It works if I write my buffer to a temp file and then use fs.createReadStream but that is really messy, slow, and not fun. I just want to send my data that is already available in memory without having to jump through hoops.

@clavin
Copy link
Contributor

clavin commented Mar 25, 2017

Took me quite a bit of searching to look for the issue, but it lies in the fact that the module request uses, form-data, only recognizes certain stream objects as files when evaluating what is a file and what is a multi-part data parameter:

Form-Data can recognize and fetch all the required information from common types of streams (fs.readStream, http.response and mikeal's request), for some other types of streams you'd need to provide "file"-related information manually:

So the fix would be to supply the extra information that form-data expects (just the file name at minimum) when submitting a buffer.

This should be implemented by the SDK in the future, but in the meantime, here's how you'd go about uploading a buffer as a file:

web.files.upload(
  fileName,
  {
    file: {
      value: fileBufferData,
      options: {
        filename: fileName,
        contentType: 'mime-type', // optional, will be guessed by `form-data` module
        knownLength: fileBufferData.length // optional, will be deduced by `form-data` module
      }
    }
  }
);

Note: I'm using an undocumented (but 2-year-old) method of forwarding formData options to the form-data module. I chose this method as it is the best choice when it comes to modifying this SDK as the way the request module suggests (using the requestObj.form() method) would require quite a bit of refactoring of how the SDK generates and sends requests.

@aoberoi aoberoi added the bug M-T: A confirmed bug report. Issues are confirmed when the reproduction steps are documented label Jun 19, 2017
@aoberoi
Copy link
Contributor

aoberoi commented Jun 19, 2017

@clavin i want to say thank you so much for your help in pinpointing this problem! you rock!

im triaging old issues and since this is reproducible, im labeling it as a bug. i hope that someone in the community can pick it up (it seems fairly obvious now that you've spelled out the solution) and send a PR. if not, it may take a little while for it to get picked up given our current prioritization.

@aoberoi aoberoi changed the title How to upload Buffer using files.upload? fix files.upload from Buffer with formData options Oct 3, 2017
@aoberoi aoberoi added this to the v3.15.0 milestone Oct 27, 2017
jmg1138 added a commit to unblinking/unblinkingbot that referenced this issue Dec 3, 2017
aoberoi added a commit to aoberoi/node-slack-sdk that referenced this issue Dec 20, 2017
aoberoi added a commit that referenced this issue Dec 20, 2017
adds file metadata for files.upload, fixes #307
KharitonOff added a commit to KharitonOff/node-slack-sdk that referenced this issue Mar 14, 2018
KharitonOff added a commit to KharitonOff/node-slack-sdk that referenced this issue Mar 15, 2018
@007souvikdas
Copy link

Took me quite a bit of searching to look for the issue, but it lies in the fact that the module request uses, form-data, only recognizes certain stream objects as files when evaluating what is a file and what is a multi-part data parameter:

Form-Data can recognize and fetch all the required information from common types of streams (fs.readStream, http.response and mikeal's request), for some other types of streams you'd need to provide "file"-related information manually:

So the fix would be to supply the extra information that form-data expects (just the file name at minimum) when submitting a buffer.

This should be implemented by the SDK in the future, but in the meantime, here's how you'd go about uploading a buffer as a file:

web.files.upload(
  fileName,
  {
    file: {
      value: fileBufferData,
      options: {
        filename: fileName,
        contentType: 'mime-type', // optional, will be guessed by `form-data` module
        knownLength: fileBufferData.length // optional, will be deduced by `form-data` module
      }
    }
  }
);

Note: I'm using an undocumented (but 2-year-old) method of forwarding formData options to the form-data module. I chose this method as it is the best choice when it comes to modifying this SDK as the way the request module suggests (using the requestObj.form() method) would require quite a bit of refactoring of how the SDK generates and sends requests.

this really saved my day

@ChuckJonas
Copy link

trying to get this to work in the deno workspace functions with a file downloaded fetch response... Anyone had any success with something similar?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug M-T: A confirmed bug report. Issues are confirmed when the reproduction steps are documented good first issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants