简体   繁体   English

为什么将文件上传到 Slack 的两种(几乎)相似的方法(使用 c#)会导致不同的结果?

[英]Why do two (almost) similar methods(using c#) of uploading a file to Slack cause different outcomes?

so this question baffels me.所以这个问题让我感到困惑。 I'll post quite abit of code to explain this one.我将发布相当多的代码来解释这一点。 First, I have and "old" version of code(c#), which I used to post messages and files to Slack.首先,我有“旧”版本的代码(c#),我用它来向 Slack 发布消息和文件。 And this code works fine for me!这段代码对我来说很好用! The method of interest is the following:感兴趣的方法如下:

public class PostMessage
    {       
        private string _token = "xoxp-MyToken";
        public string token { get { return _token; } }

        public string channel { get; set; }

        public string text { get; set; }

        public MultipartFormDataContent UploadFile()
        {
            var requestContent = new MultipartFormDataContent();
            var fileContent = new StreamContent(GetFile.ReadFile());
            requestContent.Add(new StringContent(token), "token");
            requestContent.Add(new StringContent(channel), "channels");
            requestContent.Add(fileContent, "file", Path.GetFileName(GetFile.path));

            return requestContent;
        }

    public static class GetFile
    {
        public static string path = @"C:\Users\f.held\Desktop\Held-Docs\Download.jpg";

        public static FileStream ReadFile()
        {            
            FileInfo fileInfo = new FileInfo(path);
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
            return fs;
        }
    }

Here is my client:这是我的客户:

    public class SlackClient
    {
        public Uri _method { get; set; }
        private readonly HttpClient _httpClient = new HttpClient {};

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

        public async Task<HttpResponseMessage> UploadFileAsync(MultipartFormDataContent requestContent)
        {           
            var response = await _httpClient.PostAsync(_method, requestContent);

            return response;
        }
}

And I call all of this in this Main:我在这个 Main 中调用所有这些:

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

            private static async Task TalkToSlackAsync()
            {

                            var webhookUrl = new Uri("https://slack.com/api/files.upload");
                            var slackClient = new SlackClient(webhookUrl);

                            PostMessage PM = new PostMessage();
                            PM.channel = "DCW21NBHD";

                            var cont = PM.UploadFile();

                            var response = await slackClient.UploadFileAsync(cont);
                            string content = await response.Content.ReadAsStringAsync();
        }          
}

So far, so good!到现在为止还挺好! But now it gets interesting.但现在它变得有趣了。 I build a similar version, in which I use Newtonsoft's Json NuGet-package我构建了一个类似的版本,其中我使用了 Newtonsoft 的 Json NuGet-package

Now, first the code:现在,首先是代码:

the client:客户端:

    public async Task<HttpResponseMessage> SendFileAsync(MultipartFormDataContent requestContent)
    {
        _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "xoxp-MyToken");
        var response = await _httpClient.PostAsync(UriMethod, requestContent);

        return response;
    }

the same Filestram-method for reading the file:用于读取文件的相同 Filestram 方法:

public class Message
{
    public class GetFile // Just pass a path here as parameter!
    {
        public static string path = @"C:\Users\f.held\Desktop\Held-Docs\Download.jpg";

        public static FileStream ReadFile()
        {
            FileInfo fileInfo = new FileInfo(path);
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
            return fs;
        }
    }

the Json-class which I serialize:我序列化的 Json 类:

public class JsonObject

    {
            [JsonProperty("file")]
            public string file { get; set; }
            [JsonProperty("channels")]
            public string channels { get; set; }
    }

And the Main:和主要:

class MainArea
{
    public static void Main( string[] args)
    {
        try
        {
            Task.WaitAll(SendMessage());
        }
        catch(Exception dudd)
        {
            Console.WriteLine(dudd);
            Console.ReadKey();
        }
    }
    private static async Task SendMessage()
    {
        var client = new BpsHttpClient("https://slack.com/api/files.upload");
        JsonObject JO = new JsonObject();
        JO.channels = "DCW21NBHD";

        var Json = JsonConvert.SerializeObject(JO, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

        var StringJson = new StringContent(Json, Encoding.UTF8, "multipart/form-data");
        var DeSon = JsonConvert.DeserializeObject(Json);

        Console.WriteLine(DeSon);
        Console.ReadKey();

        var requestContent = new MultipartFormDataContent();
        var fileContent = new StreamContent(Message.GetFile.ReadFile());
        requestContent.Add(fileContent, "file", Path.GetFileName(Message.GetFile.path));
        requestContent.Add(StringJson);

        var ResponseFile = await client.SendFileAsync(requestContent);

        Console.WriteLine(ResponseFile);
        Console.ReadKey();
    }
}

So, both SEEM to work.所以,两者似乎都可以工作。 But the latter of these methods does NOT post the file to the declared channel - it merely uploads it to Slack.但是这些方法中的后者不会将文件发布到声明的频道——它只是将它上传到 Slack。 Which would be fine, because I could then work with the 'public_url' to publicise it on any channel.这很好,因为我可以使用“public_url”在任何频道上宣传它。 BUT - BIG BUT - with the first method, it immediately loads it to my channel!但是 -大但是- 使用第一种方法,它会立即将其加载到我的频道! And it tells me so in the response I get from Slack.它在我从 Slack 得到的回复中告诉我。 The responses are in both exactly the same - except for the timestamps and file_id etc. obviously.响应完全相同 - 除了时间戳和 file_id 等显然。 But the ending is different!但结局不一样! Here is the ending of the response from the old version:这是旧版本响应的结尾:

"shares":{"private":{"DCW21NBHD":[{"reply_users":[],"reply_users_count":0,"reply_count":0,"ts":"1544025773.001700"}]}},"channels":[],"groups":[],"ims":["DCW21NBHD"]}}

and here is the answer from the new version:这是新版本的答案:

"shares":{},"channels":[],"groups":[],"ims":[]}}

Okay now, why on god's green earth does one method do that and the other one does not?好吧,为什么在上帝的绿色地球上,一种方法可以做到而另一种方法则不然? :D :D

Thanks to anybody who has some insight and knowledge on this specific "issue" and is willing to share!感谢任何对这个特定“问题”有一些见解和知识并愿意分享的人!

As stated in the documentation for files.upload :正如files.upload的文档中files.upload

Present arguments as parameters in application/x-www-form-urlencoded querystring or POST body.将参数作为application/x-www-form-urlencoded查询字符串或 POST 正文中的参数application/x-www-form-urlencoded This method does not currently accept application/json .此方法目前不接受application/json

So the reason this does not work is that you are trying to provide the API parameters like channels as JSON, when this method does not support JSON.因此,这不起作用的原因是当此方法不支持 JSON 时,您正在尝试将channels等 API 参数提供为 JSON。 The result is that those properties are ignore, which is why the image is uploaded, but not shared in the designated channel.结果是这些属性都被忽略了,这就是为什么上传图片,但没有在指定频道中共享的原因。

To fix it simply provide your parameters as application/x-www-form-urlencoded querystring as you did in your 1st example.要修复它,只需像在第一个示例中所做的那样将参数作为application/x-www-form-urlencoded查询字符串提供。

Note that in general only a subset of the Slack API methods support using JSON for providing the parameters as listed here .请注意,通常只有 Slack API 方法的一个子集支持使用 JSON 来提供此处列出的参数。 If you want to use JSON, please double-check if the API method supports it, or stick with x-www-form-urlencoded (which is the standard for POST) to be on the safe side.如果你想使用 JSON,请仔细检查 API 方法是否支持它,或者坚持使用x-www-form-urlencoded (这是 POST 的标准)以确保安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C# 不同但相似的命名空间导致错误 - C# Different but similar Namespaces cause errors 使用具有不同属性的多个类似方法的 C# 最佳实践? - C# best practice with using multiple similar methods with different properties? 在C#中,有两种将gif文件转换为byte []的方法 - In C#,two different methods to convert a gif file to byte[] C#委托给两个具有不同参数的方法 - C# delegate for two methods with different parameters 有没有什么方法可以在C#中使用MailMessage设置电子邮件个人资料图片,或者可以使用任何类似的方法来设置? - Is there any way to set email profile picture using MailMessage in C# or any similar methods that may do that? 在C#中,为什么在这种情况下使用字段与自动实现的属性会导致不同的行为? - In C#, why does using a field vs. an auto-implemented property cause different behavior in this case? 在C#和Linq中使用泛型参数重构相似的方法 - Refactoring similar methods using generics parameter in c# and linq 使用C#将文件上传到服务器 - Uploading a file to server using c# 使用WebClient(C#)上传文件不一致 - Inconsistent in uploading a file using webclient (C#) 为什么C#为`using`定义了两种不同的用途? - Why does C# define two different uses for `using`?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM