I want to send a message and photo to a channel with my bot in c# 2013, but I'm getting The remote server returned an error: (400) Bad Request

I want to send a message and photo to a channel with my bot in c# 2013, but I'm getting The remote server returned an error: (400) Bad Request

我想在 c# 2013 中使用我的机器人向频道发送消息和照片。 消息和照片应该在一个盒子里发送。照片在消息上方。

我可以成功向频道发送消息,但是有两个问题:

  1. 发送照片时,出现此错误:

The remote server returned an error: (400) Bad Request.

  1. 我无法在一次发送中将文字和照片一起发送。

代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Telegram.Bot;
    using Telegram.Bot.Types;
    using System.Net;

    namespace SendTxt-Photo
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
         string  Token = "adasdsadsadsadasds";
          string  channel_id = "@BestLaptop";

            private void Form1_Load(object sender, EventArgs e)
            {

            }


  private void button1_Click(object sender, EventArgs e)
        {

         using (var stream = File.Open(@"image/1.jpg", FileMode.Open))
          {
           WebRequest req = WebRequest.Create("https://api.telegram.org/bot" + Token + "/sendMessage?chat_id=" + channel_id + "&text=" + textbox1.text);
                       req.UseDefaultCredentials = true;
          WebRequest req1 = WebRequest.Create("https://api.telegram.org/bot" + Token + "/sendPhoto?chat_id=" + channel_id + "&Photo=" + stream );
                       req.UseDefaultCredentials = true;
                       req1.UseDefaultCredentials = true;

                        var result = req.GetResponse();
                        req.Abort();

                         var result1 = req1.GetResponse();
                        req1.Abort();


                }

            }
        }
    }

首先您必须知道您发送的是...&photo=Sistem.IO.FileStream而不是您的文件。这是错误请求的根本原因。在调试中查看。

第二个正如你在api documentation中看到的sendPhoto方法提供了三种类型的photo参数:

Pass a file_id as String to send a photo that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a photo from the Internet, or upload a new photo using multipart/form-data.

所以根据您的情况需要使用 multipart/form-data。可以用RestSharp for example like (code was generated by Postman简化,没测试过):

var client = new RestClient("https://api.telegram.org/botadasdsadsadsadasds/sendPhoto");
        var request = new RestRequest(Method.POST);
        request.AddHeader("cache-control", "no-cache");
        request.AddHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
        request.AddParameter("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"chat_id\"\r\n\r\n@BestLaptop\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"1.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
        IRestResponse response = client.Execute(request);

在第三个,您不能在一条消息中的文字上方发送照片。要在一条消息中发送文本和照片,请使用 sendPhoto 方法的 caption 参数。它提供 200 个符号长度。

PS 为什么不使用 Telegram.Bot nuget 包?

此函数是上传文件的助手:

        public static string UploadFilesToRemoteUrl(HttpWebRequest request, string[] files, NameValueCollection formFields = null)
    {
        string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");

        request.ContentType = "multipart/form-data; boundary=" + boundary;
        request.Method = "POST";
        request.KeepAlive = true;

        Stream memStream = new System.IO.MemoryStream();

        var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
                                                                boundary + "\r\n");
        var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
                                                                    boundary + "--");


        string formdataTemplate = "\r\n--" + boundary +
                                    "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

        if (formFields != null)
        {
            foreach (string key in formFields.Keys)
            {
                string formitem = string.Format(formdataTemplate, key, formFields[key]);
                byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
                memStream.Write(formitembytes, 0, formitembytes.Length);
            }
        }

        string headerTemplate =
            "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
            "Content-Type: application/octet-stream\r\n\r\n";

        for (int i = 0; i < files.Length; i++)
        {
            memStream.Write(boundarybytes, 0, boundarybytes.Length);
            var header = string.Format(headerTemplate, "photo", files[i]);
            var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);

            memStream.Write(headerbytes, 0, headerbytes.Length);

            using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))
            {
                var buffer = new byte[1024];
                var bytesRead = 0;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                }
            }
        }

        memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
        request.ContentLength = memStream.Length;

        using (Stream requestStream = request.GetRequestStream())
        {
            memStream.Position = 0;
            byte[] tempBuffer = new byte[memStream.Length];
            memStream.Read(tempBuffer, 0, tempBuffer.Length);
            memStream.Close();
            requestStream.Write(tempBuffer, 0, tempBuffer.Length);
        }

        using (var response = request.GetResponse())
        {
            Stream stream2 = response.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            return reader2.ReadToEnd();
        }
    }

这里是发送文件的代码(用于 Roscomnadzor 的代理)使用你的变量而不是 msg.GetParam({""}) 你需要 chat_id, bot_id,photo和标题。如果你需要,"proxy"。

                string filePath = msg.GetParam("photo");
            string URL = "https://api.telegram.org/bot" + msg.GetParam("bot_id") + "/sendPhoto";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            WebProxy myProxy = new WebProxy(msg.GetParam("proxy"));
            myProxy.UseDefaultCredentials = true;
            request.Proxy = myProxy;

            string[] variable_name = {filePath};
            NameValueCollection form = new NameValueCollection();
            form["chat_id"] = msg.GetParam("chat_id");
            form["caption"] = msg.GetParam("caption");
            UploadFilesToRemoteUrl(request, variable_name, form);