如何通过C#

时间:2018-11-12 14:20:05

标签: c# slack slack-api

我需要将文件上传到Slack的帮助。

到目前为止,我有一个正在使用我的代码的Slack-App。但是我所能做的就是发布消息。我无法将图像附加到消息上-因为我不了解如何使用所谓的“方法”,并且Slack在其API页面上“显示”语法。

这将创建我的“内容”,并且在其下方是一个流,用于读取我可以上传的文件:

    public class PostMessage
    {


        public FormUrlEncodedContent Content(string message, string file)
        {
            var values = new Dictionary<string, string>
            {
                {"token", "xoxp-myToken"},
                { "username", "X"},         
                { "channel", "myChannel"},
                { "as_user", "false"},     
                {"text", message},
                { "content", file},
                { "attachments","[{ \"fallback\":\"dummy\", \"text\":\"this is a waste of time\"}]"}
            };

            var content = new FormUrlEncodedContent(values);

            return content;
        }
    }

    public class PostFile
    {
        String path = @"C:\Users\f.held\Desktop\Held-Docs\dagged.jpg";

        public string ReadImageFile()
        {            
            FileInfo fileInfo = new FileInfo(path);
            long imageFileLength = fileInfo.Length;
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            byte[] imageData = br.ReadBytes((int)imageFileLength);
            var str = Encoding.Default.GetString(imageData);
            return str;
        }
    }
}  

通信的客户端:

public class SlackClient
{
        private readonly Uri _webhookUrl;
        private readonly HttpClient _httpClient = new HttpClient {};

        public SlackClient(Uri webhookUrl)
        {
            _webhookUrl = webhookUrl;
        }

        public async Task<HttpResponseMessage> SendMessageAsync(FormUrlEncodedContent content)
        {
            var response = await _httpClient.PostAsync(_webhookUrl, content);

            return response;
        }    
     }
}

主要:

public static void Main(string[] args)
{
    Task.WaitAll(IntegrateWithSlackAsync());
}

private static async Task IntegrateWithSlackAsync()
{
    var webhookUrl = new Uri("https://slack.com/api/files.upload");
    var slackClient = new SlackClient(webhookUrl);
    PostMessage PM = new PostMessage();
    PostFile PF = new PostFile();


    while (true)
    {
        Console.Write("Type a message: ");
        var message = Console.ReadLine();
        var testFile = PF.ReadImageFile();
        FormUrlEncodedContent payload = PM.Content(message, testFile);
        var response = await slackClient.SendMessageAsync(payload);
        var isValid = response.IsSuccessStatusCode ? "valid" : "invalid";
        Console.WriteLine($"Received {isValid} response.");
        Console.WriteLine(response);
        response.Dispose();
    }
}

} }

如果有人举了一个例子,说明上传必须是什么样子。甚至更好,

如果有人真的可以解释这些Slack-Messages必须具有的语法。

那太好了!我仍然不知道我应该在哪里以及如何放置所谓的 “可接受的内容类型:multipart / form-data,application / x-www-form-urlencoded” 到我的上传文件中。我只是找不到关于此的示例...

修改:

让我大吃一惊的是,Slack声明它们有一个名为file.upload的额外方法-但是我们不应该再使用它了,我们应该只使用postMessage

但是我如何在邮件中“打包”文件?我的语法似乎总是不正确。特别是在“内容”方面... 我只是无法弄清楚C#代码的外观。我在哪里声明上述“内容类型”?

另一个问题是,它总是通过以下方式发送我的消息-表示我从服务器收到200条响应。但是它从不显示文件(这可能意味着语法已关闭),或者我得到了200条响应,但是消息却从未在Slack中显示。

3 个答案:

答案 0 :(得分:2)

邮件中的图片

如果您想在邮件中包含图片(以及一些文本),可以通过将图片作为邮件附件添加到以chat.postMessage发送的普通邮件中来实现。

为此,您需要图像的公共URL,并带有image_url属性链接到附件。该附件也可以包含文本,您可以在邮件中添加多个附件。

它是这样的:

enter image description here

这是此消息在JSON中的外观:

{
    "channel": "test",
    "text": "This is a message example with images in the attachment",
    "attachments": [
        {
            "fallback": "game over",
            "text": "This is some text in the attachement",
            "image_url": "https://i.imgur.com/jO9N3eJ.jpg"

        }
    ]
}

上传图片

图像URL需要在Internet上公开访问。因此,您需要将图像文件托管在公共网络服务器上,或者将其上传到图像云服务(例如imgur.com)。

您还可以将Slack用作图像的云服务。运作方式如下:

  1. 上传到Slack:使用files.upload

  2. 将图像上传到Slack工作区
  3. 获取公共URL:使用files.sharedPublicURL获取图像文件的公共URL。通常,Slack上的所有文件都是私有文件,但是您只能将公共URL用于邮件附件。

  4. 发送消息:将图像作为附件包括在消息中:使用图像文件的permalink_public属性作为image_url的值

示例代码

这是C#中完整的工作示例,首先将图像上传到Slack,然后在消息中使用它。

注意:此示例需要Newtonsoft.Json

using System;
using System.Net;
using System.Collections.Specialized;
using System.Text;
using Newtonsoft.Json;

public class SlackExample
{
    // classes for converting JSON respones from API method into objects
    // note that only those properties are defind that are needed for this example

    // reponse from file methods
    class SlackFileResponse
    {
        public bool ok { get; set; }
        public String error { get; set; }
        public SlackFile file { get; set; }
    }

    // a slack file
    class SlackFile
    {
        public String id { get; set; }        
        public String name { get; set; }
        public String permalink_public { get; set; }
    }

    // reponse from message methods
    class SlackMessageResponse
    {
        public bool ok { get; set; }
        public String error { get; set; }
        public String channel { get; set; }
        public String ts { get; set; }        
    }

    // a slack message attachment
    class SlackAttachment
    {
        public String fallback { get; set; }
        public String text { get; set; }
        public String image_url { get; set; }
    }

    // main method with logic
    public static void Main()
    {
        String token = "xoxp-YOUR-TOKEN";


        /////////////////////
        // Step 1: Upload file to Slack

        var parameters = new NameValueCollection();

        // put your token here
        parameters["token"] = token;

        var client1 = new WebClient();
        client1.QueryString = parameters;
        byte[] responseBytes1 = client1.UploadFile(
                "https://slack.com/api/files.upload",
                "C:\\Temp\\Stratios_down.jpg"
        );

        String responseString1 = Encoding.UTF8.GetString(responseBytes1);

        SlackFileResponse fileResponse1 = 
            JsonConvert.DeserializeObject<SlackFileResponse>(responseString1);

        String fileId = fileResponse1.file.id;


        /////////////////////
        // Step 2: Make file public and get the URL

        var parameters2 = new NameValueCollection();
        parameters2["token"] = token;
        parameters2["file"] = fileId;

        var client2 = new WebClient();
        byte[] responseBytes2 = client2.UploadValues("https://slack.com/api/files.sharedPublicURL", "POST", parameters2);

        String responseString2 = Encoding.UTF8.GetString(responseBytes2);

        SlackFileResponse fileResponse2 =
            JsonConvert.DeserializeObject<SlackFileResponse>(responseString2);

        String imageUrl = fileResponse2.file.permalink_public;


        /////////////////////
        // Step 3: Send message including freshly uploaded image as attachment

        var parameters3 = new NameValueCollection();
        parameters3["token"] = token;
        parameters3["channel"] = "test_new";        
        parameters3["text"] = "test message 2";

        // create attachment
        SlackAttachment attachment = new SlackAttachment();
        attachment.fallback = "this did not work";
        attachment.text = "this is anattachment";
        attachment.image_url = imageUrl;
        SlackAttachment[] attachments = { attachment };        
        parameters3["attachments"] = JsonConvert.SerializeObject(attachments);

        var client3 = new WebClient();
        byte[] responseBytes3 = client3.UploadValues("https://slack.com/api/chat.postMessage", "POST", parameters3);

        String responseString3 = Encoding.UTF8.GetString(responseBytes3);

        SlackMessageResponse messageResponse =
            JsonConvert.DeserializeObject<SlackMessageResponse>(responseString3);

    }
}

答案 1 :(得分:1)

这是一个简短的工作示例,展示了如何仅使用C#将任何文件上传到Slack。该示例还将自动在给定的频道上共享文件。

我已经包含了从JSON转换API响应的逻辑,这将始终需要以确定API调用是否成功。

注意:此示例需要Newtonsoft.Json

using System;
using System.Net;
using System.Collections.Specialized;
using System.Text;
using Newtonsoft.Json;

public class SlackExample
{
    // classes for converting JSON respones from API method into objects
    // note that only those properties are defind that are needed for this example

    // reponse from file methods
    class SlackFileResponse
    {
        public bool ok { get; set; }
        public String error { get; set; }
        public SlackFile file { get; set; }
    }

    // a slack file
    class SlackFile
    {
        public String id { get; set; }
        public String name { get; set; }        
    }

    // main method with logic
    public static void Main()
    {
        var parameters = new NameValueCollection();

        // put your token here
        parameters["token"] = "xoxp-YOUR-TOKEN";
        parameters["channels"] = "test";

        var client = new WebClient();
        client.QueryString = parameters;
        byte[] responseBytes = client.UploadFile(
                "https://slack.com/api/files.upload",
                "D:\\temp\\Stratios_down.jpg"
        );

        String responseString = Encoding.UTF8.GetString(responseBytes);

        SlackFileResponse fileResponse =
            JsonConvert.DeserializeObject<SlackFileResponse>(responseString);
    }
}

关于内容类型:这些内容是HTTP请求标头的一部分,可以在WebClient对象中手动设置(另请参见this answer)。但是,对于我们来说,您可以忽略它,因为WebClient用于POST请求的默认内容类型可以正常工作。

另请参见this answer,以了解如何使用WebClient类上传文件。

答案 2 :(得分:1)

这是另一个将文件上传到Slack的完整示例,这一次是通过 async 方法与HttpClient一起使用的。

注意:此示例需要Newtonsoft.Json

using Newtonsoft.Json;
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

namespace SlackExample
{
    class UploadFileExample
    {
        private static readonly HttpClient client = new HttpClient();

        // classes for converting JSON respones from API method into objects
        // note that only those properties are defind that are needed for this example

        // reponse from file methods
        class SlackFileResponse
        {
            public bool ok { get; set; }
            public String error { get; set; }
            public SlackFile file { get; set; }
        }

        // a slack file
        class SlackFile
        {
            public String id { get; set; }
            public String name { get; set; }
        }

        // sends a slack message asynchronous
        // throws exception if message can not be sent
        public static async Task UploadFileAsync(string token, string path, string channels)
        {
            // we need to send a request with multipart/form-data
            var multiForm = new MultipartFormDataContent();

            // add API method parameters
            multiForm.Add(new StringContent(token), "token");
            multiForm.Add(new StringContent(channels), "channels");

            // add file and directly upload it
            FileStream fs = File.OpenRead(path);
            multiForm.Add(new StreamContent(fs), "file", Path.GetFileName(path));

            // send request to API
            var url = "https://slack.com/api/files.upload";
            var response = await client.PostAsync(url, multiForm);

            // fetch response from API
            var responseJson = await response.Content.ReadAsStringAsync();

            // convert JSON response to object
            SlackFileResponse fileResponse =
                JsonConvert.DeserializeObject<SlackFileResponse>(responseJson);

            // throw exception if sending failed
            if (fileResponse.ok == false)
            {
                throw new Exception(
                    "failed to upload message: " + fileResponse.error
                );
            }
            else
            {
                Console.WriteLine(
                        "Uploaded new file with id: " + fileResponse.file.id
                );
            }
        }

        static void Main(string[] args)
        {
            // upload this file and wait for completion
            UploadFileAsync(
                "xoxp-YOUR-TOKEN",
                "C:\\temp\\Stratios_down.jpg",
                "test"
            ).Wait();

            Console.ReadKey();

        }
    }

}