Почему два (почти) похожих метода (с использованием c #) загрузки файла в Slack приводят к разным результатам? - PullRequest
0 голосов
/ 05 декабря 2018

так что этот вопрос сбивает меня с толку.Я опубликую немного кода, чтобы объяснить это.Во-первых, у меня есть и «старая» версия кода (c #), которую я использовал для публикации сообщений и файлов в Slack.И этот код прекрасно работает для меня!Интересующий метод заключается в следующем:

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

Вот мой клиент:

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

И я называю все это в этом 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();
        }          
}

Пока все хорошо!Но теперь это становится интересным.Я создаю аналогичную версию, в которой я использую JSON NuGet-пакет Newtonsoft

Теперь сначала код:

клиент:

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

тот же 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;
        }
    }

JSON-класс, который я сериализую:

public class JsonObject

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

А главное:

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

Итак, оба SEEM работают.Но последний из этих методов НЕ публикует файл на объявленном канале - он просто загружает его в Slack.Это было бы хорошо, потому что тогда я мог бы работать с public_url, чтобы опубликовать его на любом канале.НО - БОЛЬШОЙ НО - при первом способе он немедленно загружает его на мой канал!И это говорит мне об этом в ответе от Slack.Ответы в обоих случаях одинаковы - за исключением временных меток, file_id и т. Д., Очевидно.Но концовка другая! Вот окончание ответа от старой версии:

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

и вот ответ от новой версии:

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

Хорошо, почему на зеленой земле Бога один метод делает это, а другой нет?: D

Спасибо всем, кто имеет некоторое понимание и знание по этой конкретной "проблеме" и готов поделиться!

1 Ответ

0 голосов
/ 05 декабря 2018

Как указано в документации для files.upload:

Представлять аргументы в качестве параметров в application/x-www-form-urlencoded строке запроса или теле POST.Этот метод в настоящее время не принимает application/json.

Поэтому причина, по которой это не работает, заключается в том, что вы пытаетесь предоставить параметры API, такие как channels, в качестве JSON, когда этот метод не поддерживает JSON,В результате эти свойства игнорируются, поэтому изображение загружается, но не передается в назначенный канал.

Чтобы исправить это, просто укажите свои параметры в виде application/x-www-form-urlencoded строки запроса, как вы делали в первом примере..

Обратите внимание, что в целом только подмножество методов Slack API поддерживают использование JSON для предоставления параметров, перечисленных здесь .Если вы хотите использовать JSON, перепроверьте, поддерживает ли метод API его, или придерживайтесь x-www-form-urlencoded (который является стандартом для POST), чтобы быть в безопасности.

...