【问题标题】:How to upload an image to Slack using node.js on Windows?如何在 Windows 上使用 node.js 将图像上传到 Slack?
【发布时间】:2018-02-06 20:51:08
【问题描述】:

我正在尝试使用 node.js 和 request package 通过 Slack 上传图像,但运气不佳。我从 API 收到 invalid_array_argno_file_data 错误。

这是我的要求:

    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);
    });

我看了一些相关的帖子:

唯一有效的是直接使用 curl 命令,但使用 cygwin(CommandPrompt 失败:curl: (1) Protocol https not supported or disabled in libcurl)。从节点调用 curl 的问题(使用 child_process)但在命令提示符中静默失败,仍然使用 cygwin 返回 no_file_data(将绝对路径传递给文件):

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

我在 Windows 上使用节点 v6.9.1。

我错过了什么?如何在 Windows 上通过 node.js 将图像上传到 slack?

【问题讨论】:

  • 我知道这不是您问题的答案,也许您应该考虑使用node-slack-sdk/,在这种情况下您不需要自己实现这些功能。 file upload documentation
  • @Peter 使用 node-slack-sdk:error: Response not OK: no_file_data Error: no_file_data 出人意料地得到了同样的错误
  • @GeorgeProfenza 要走的路是files.upload
  • 为什么您的 #2 链接问题的解决方案不适合您? (stackoverflow.com/questions/38084459/…) 你试过用同样的语法重现吗?
  • @Tanaike 我希望我能给你不止一票。两种解决方案都有效!与此同时,我进行了更多测试并发现了问题:我尝试在图像完全写入磁盘之前上传图像。一旦我确保文件完全写入磁盘,第二种方法也可以使用。有趣的是,即使图像没有完全写入磁盘,您的第一种方法(手动创建多部分标头)也能正常工作:它只是为丢失的数据显示灰色像素。

标签: javascript node.js file-upload slack slack-api


【解决方案1】:

Slack API 错误invalid_array_arg 表示传递给 Slack 的参数格式存在问题。 (见here

当为files.upload 使用file 属性时,Slack 将数据排除为multipart/form-data,而不是application/x-www-form-urlencoded。因此,您需要在请求对象中使用formData 而不是form。我还删除了标题中不正确的部分。

这行得通:

      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);
    });

【讨论】:

  • 感谢您的回答。我已经尝试按照您上面的建议使用formData,不幸的是我遇到了同样的错误。我将进行更多测试。也许我上传的数据还没有准备好?
  • @GeorgeProfenza 此代码已经过测试并且可以工作。我添加了初始化只是为了确保。你试过这个确切的代码吗?请告诉我您从 API 中得到的确切错误。
  • 抱歉耽搁了。我做了一些进一步的测试,找到了问题的根源:不是请求本身,而是数据和 createReadStream 结果。在上传之前,我没有等待上传的图像完全写入磁盘。现在已修复,您的代码和 Tanaike 的代码都可以工作。他的手动多部分方法的有趣之处在于,即使 jpeg 没有完全写入磁盘(以正确的尺寸显示 jpeg 并带有一小部分灰色像素),它也能工作
【解决方案2】:

在这个示例脚本中,它假设上传一个二进制文件(zip 文件)。当您使用它时,请根据您的环境进行修改。当文件上传到 Slack 时,使用 multipart/form-data。在我的环境中,有一些库无法上传文件的情况。所以我创造了这个。如果这对您的环境有用,我很高兴。

用户可以通过以下方式转换字节数组来上传二进制文件。

  • 首先,它构建表单数据。
  • 添加使用 Buffer.concat() 转换为字节数组和边界的 zip 文件。
  • 这在请求中用作正文。

示例脚本如下。

示例脚本:

var fs = require('fs');
var request = require('request');
var upfile = 'sample.zip';
fs.readFile(upfile, function(err, content){
    if(err){
        console.error(err);
    }
    var metadata = {
        token: "### access token ###",
        channels: "sample",
        filename: "samplefilename",
        title: "sampletitle",
    };
    var url = "https://slack.com/api/files.upload";
    var boundary = "xxxxxxxxxx";
    var data = "";
    for(var i in metadata) {
        if ({}.hasOwnProperty.call(metadata, i)) {
            data += "--" + boundary + "\r\n";
            data += "Content-Disposition: form-data; name=\"" + i + "\"; \r\n\r\n" + metadata[i] + "\r\n";
        }
    };
    data += "--" + boundary + "\r\n";
    data += "Content-Disposition: form-data; name=\"file\"; filename=\"" + upfile + "\"\r\n";
    data += "Content-Type:application/octet-stream\r\n\r\n";
    var payload = Buffer.concat([
            Buffer.from(data, "utf8"),
            new Buffer(content, 'binary'),
            Buffer.from("\r\n--" + boundary + "\r\n", "utf8"),
    ]);
    var options = {
        method: 'post',
        url: url,
        headers: {"Content-Type": "multipart/form-data; boundary=" + boundary},
        body: payload,
    };
    request(options, function(error, response, body) {
        console.log(body);
    });
});

【讨论】:

    猜你喜欢
    • 2023-01-04
    • 1970-01-01
    • 1970-01-01
    • 2022-06-18
    • 1970-01-01
    • 2021-12-10
    • 2016-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多