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)
...
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.
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.
@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.
Took me quite a bit of searching to look for the issue, but it lies in the fact that the module
requestuses,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-dataexpects (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
formDataoptions to theform-datamodule. 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 therequestObj.form()method) would require quite a bit of refactoring of how the SDK generates and sends requests.
this really saved my day
Most helpful comment
Took me quite a bit of searching to look for the issue, but it lies in the fact that the module
requestuses,form-data, only recognizes certain stream objects as files when evaluating what is a file and what is a multi-part data parameter:So the fix would be to supply the extra information that
form-dataexpects (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:
Note: I'm using an undocumented (but 2-year-old) method of forwarding
formDataoptions to theform-datamodule. 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 therequestObj.form()method) would require quite a bit of refactoring of how the SDK generates and sends requests.